* Copyright 2001-2016, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* DarkWyrm <bpmagic@columbus.rr.com>
* Adrian Oanca <adioanca@cotty.iren.ro>
* Stephan Aßmus <superstippi@gmx.de>
* Stefano Ceccherini (burton666@libero.it)
* Axel Dörfler, axeld@pinc-software.de
* Jérôme Duval, jerome.duval@free.fr
* Andrej Spielmann, <andrej.spielmann@seh.ox.ac.uk>
* Philippe Saint-Pierre, stpere@gmail.com
* Wim van der Meer, <WPJvanderMeer@gmail.com>
* Joseph Groover <looncraz@looncraz.net>
*/
\brief Counterpart to BApplication within the app_server
*/
#include "ServerApp.h"
#include <new>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <AppDefs.h>
#include <Autolock.h>
#include <AutoLocker.h>
#include <Debug.h>
#include <List.h>
#include <ScrollBar.h>
#include <Shape.h>
#include <String.h>
#include <StackOrHeapArray.h>
#include <FontPrivate.h>
#include <MessengerPrivate.h>
#include <PrivateScreen.h>
#include <RosterPrivate.h>
#include <ServerProtocol.h>
#include <WindowPrivate.h>
#include "AppFontManager.h"
#include "AppServer.h"
#include "BitmapManager.h"
#include "CursorManager.h"
#include "CursorSet.h"
#include "Desktop.h"
#include "DecorManager.h"
#include "DrawingEngine.h"
#include "EventStream.h"
#include "GlobalFontManager.h"
#include "HWInterface.h"
#include "InputManager.h"
#include "OffscreenServerWindow.h"
#include "Screen.h"
#include "ServerBitmap.h"
#include "ServerConfig.h"
#include "ServerCursor.h"
#include "ServerPicture.h"
#include "ServerTokenSpace.h"
#include "ServerWindow.h"
#include "Window.h"
#ifdef DEBUG_SERVERAPP
# define STRACE(x) debug_printf x
#else
# define STRACE(x) ;
#endif
#ifdef DEBUG_SERVERAPP_FONT
# define FTRACE(x) debug_printf x
#else
# define FTRACE(x) ;
#endif
using std::nothrow;
static const uint32 kMsgUpdateShowAllDraggers = '_adg';
static const uint32 kMsgAppQuit = 'appQ';
ServerApp::ServerApp(Desktop* desktop, port_id clientReplyPort,
port_id clientLooperPort, team_id clientTeam,
int32 clientToken, const char* signature)
:
MessageLooper("application"),
fMessagePort(-1),
fClientReplyPort(clientReplyPort),
fDesktop(desktop),
fSignature(signature),
fClientTeam(clientTeam),
fWindowListLock("window list"),
fInitialWorkspace(desktop->CurrentWorkspace()),
fTemporaryDisplayModeChange(0),
fMapLocker("server app maps"),
fAppCursor(NULL),
fViewCursor(NULL),
fCursorHideLevel(0),
fIsActive(false),
fMemoryAllocator(new (std::nothrow) ClientMemoryAllocator(this), true),
fAppFontManager(NULL)
{
if (fSignature.IsEmpty())
fSignature = "application/no-signature";
char name[B_OS_NAME_LENGTH];
snprintf(name, sizeof(name), "a<%" B_PRId32 ":%s", fClientTeam,
SignatureLeaf());
fMessagePort = create_port(DEFAULT_MONITOR_PORT_SIZE, name);
if (fMessagePort < B_OK)
return;
fLink.SetSenderPort(fClientReplyPort);
fLink.SetReceiverPort(fMessagePort);
fLink.SetTargetTeam(fClientTeam);
if (set_port_owner(fMessagePort, fClientTeam) < B_OK) {
delete_port(fMessagePort);
fMessagePort = -1;
return;
}
BMessenger::Private(fHandlerMessenger).SetTo(fClientTeam,
clientLooperPort, clientToken);
desktop->LockSingleWindow();
DesktopSettings settings(desktop);
settings.GetDefaultPlainFont(fPlainFont);
settings.GetDefaultBoldFont(fBoldFont);
settings.GetDefaultFixedFont(fFixedFont);
desktop->UnlockSingleWindow();
fAppFontManager = new AppFontManager();
STRACE(("ServerApp %s:\n", Signature()));
STRACE(("\tBApp port: %" B_PRId32 "\n", fClientReplyPort));
STRACE(("\tReceiver port: %" B_PRId32 "\n", fMessagePort));
}
ServerApp::~ServerApp()
{
STRACE(("*ServerApp %s:~ServerApp()\n", Signature()));
ASSERT(fQuitting);
fWindowListLock.Lock();
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
ServerWindow* window = fWindowList.ItemAt(i);
window->Quit();
}
fWindowListLock.Unlock();
snooze(20000);
fDesktop->RevertScreenModes(fTemporaryDisplayModeChange);
fWindowListLock.Lock();
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
ServerWindow* window = fWindowList.ItemAt(i);
if (window == NULL)
continue;
sem_id deathSemaphore = window->DeathSemaphore();
fWindowListLock.Unlock();
if (MessageLooper::WaitForQuit(deathSemaphore, 3000000) != B_OK) {
#ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
syslog(LOG_ERR, "ServerApp %s: ServerWindow doesn't respond!\n",
Signature());
#else
debugger("ServerWindow doesn't respond!\n");
#endif
}
fWindowListLock.Lock();
}
if (fMemoryAllocator != NULL)
fMemoryAllocator->Detach();
fMapLocker.Lock();
while (!fBitmapMap.empty())
_DeleteBitmap(fBitmapMap.begin()->second);
while (!fPictureMap.empty())
fPictureMap.begin()->second->SetOwner(NULL);
fDesktop->GetCursorManager().DeleteCursors(fClientTeam);
delete fAppFontManager;
STRACE(("ServerApp %s::~ServerApp(): Exiting\n", Signature()));
}
*/
status_t
ServerApp::InitCheck()
{
if (fMessagePort < B_OK)
return fMessagePort;
if (fClientReplyPort < B_OK)
return fClientReplyPort;
if (fWindowListLock.InitCheck() < B_OK)
return fWindowListLock.InitCheck();
if (fMemoryAllocator == NULL)
return B_NO_MEMORY;
return B_OK;
}
void
ServerApp::Quit()
{
Quit(-1);
}
to call its destructor directly.
At the point you're calling this method, the application should already
be removed from the application list.
*/
void
ServerApp::Quit(sem_id shutdownSemaphore)
{
if (fThread < B_OK) {
delete this;
return;
}
fQuitting = true;
PostMessage(kMsgAppQuit);
send_data(fThread, 'QUIT', &shutdownSemaphore, sizeof(sem_id));
}
\param value The new status of the ServerApp.
This changes an internal flag and also sets the current cursor to the one
specified by the application
*/
void
ServerApp::Activate(bool value)
{
if (fIsActive == value)
return;
fIsActive = value;
if (fIsActive) {
BRoster::Private roster;
roster.UpdateActiveApp(ClientTeam());
if (_HasWindowUnderMouse()) {
fDesktop->SetCursor(CurrentCursor());
}
fDesktop->HWInterface()->SetCursorVisible(fCursorHideLevel == 0);
}
}
void
ServerApp::SetCurrentCursor(ServerCursor* cursor)
{
fViewCursor.SetTo(cursor, false);
fDesktop->SetCursor(CurrentCursor());
}
ServerCursor*
ServerApp::CurrentCursor() const
{
if (fViewCursor != NULL)
return fViewCursor;
return fAppCursor;
}
bool
ServerApp::AddWindow(ServerWindow* window)
{
BAutolock locker(fWindowListLock);
return fWindowList.AddItem(window);
}
void
ServerApp::RemoveWindow(ServerWindow* window)
{
BAutolock locker(fWindowListLock);
fWindowList.RemoveItem(window);
}
bool
ServerApp::InWorkspace(int32 index) const
{
BAutolock locker(fWindowListLock);
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
ServerWindow* serverWindow = fWindowList.ItemAt(i);
const Window* window = serverWindow->Window();
if (window == NULL || window->IsOffscreenWindow())
continue;
if (window->IsNormal() && !window->IsHidden()
&& window->InWorkspace(index))
return true;
}
return false;
}
uint32
ServerApp::Workspaces() const
{
uint32 workspaces = 0;
BAutolock locker(fWindowListLock);
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
ServerWindow* serverWindow = fWindowList.ItemAt(i);
const Window* window = serverWindow->Window();
if (window == NULL || window->IsOffscreenWindow())
continue;
if (window->IsNormal() && !window->IsHidden())
workspaces |= window->Workspaces();
}
return workspaces;
}
\param token ID token of the bitmap to find
\return The bitmap having that ID or NULL if not found
*/
ServerBitmap*
ServerApp::GetBitmap(int32 token) const
{
if (token < 1)
return NULL;
BAutolock _(fMapLocker);
ServerBitmap* bitmap = _FindBitmap(token);
if (bitmap == NULL)
return NULL;
bitmap->AcquireReference();
return bitmap;
}
ServerPicture*
ServerApp::CreatePicture(const ServerPicture* original)
{
BReference<ServerPicture> picture;
if (original != NULL)
picture.SetTo(new(std::nothrow) ServerPicture(*original), true);
else
picture.SetTo(new(std::nothrow) ServerPicture(), true);
if (picture != NULL && !picture->SetOwner(this))
return NULL;
return picture.Detach();
}
ServerPicture*
ServerApp::GetPicture(int32 token) const
{
if (token < 1)
return NULL;
BAutolock _(fMapLocker);
ServerPicture* picture = _FindPicture(token);
if (picture == NULL)
return NULL;
picture->AcquireReference();
return picture;
}
bool
ServerApp::AddPicture(ServerPicture* picture)
{
BAutolock _(fMapLocker);
ASSERT(picture->Owner() == NULL);
try {
fPictureMap.insert(std::make_pair(picture->Token(), BReference<ServerPicture>(picture, false)));
} catch (std::bad_alloc& exception) {
return false;
}
return true;
}
void
ServerApp::RemovePicture(ServerPicture* picture)
{
BAutolock _(fMapLocker);
ASSERT(picture->Owner() == this);
fPictureMap.erase(picture->Token());
}
\param message The message to send
*/
void
ServerApp::SendMessageToClient(BMessage* message) const
{
status_t status = fHandlerMessenger.SendMessage(message, (BHandler*)NULL,
100000);
if (status != B_OK) {
syslog(LOG_ERR, "app %s send to client failed: %s\n", Signature(),
strerror(status));
}
}
void
ServerApp::_GetLooperName(char* name, size_t length)
{
snprintf(name, length, "a:%" B_PRId32 ":%s", ClientTeam(), SignatureLeaf());
}
\param code Identifier code for the message. Equivalent to BMessage::what
\param buffer Any attachments
Note that the buffer's exact format is determined by the particular message.
All attachments are placed in the buffer via a PortLink, so it will be a
matter of casting and incrementing an index variable to access them.
*/
void
ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
{
switch (code) {
case AS_REGISTER_INPUT_SERVER:
{
EventStream* stream
= new(std::nothrow) InputServerStream(fHandlerMessenger);
if (stream != NULL
&& (!stream->IsValid() || !gInputManager->AddStream(stream))) {
delete stream;
break;
}
if (fDesktop->EventDispatcher().InitCheck() != B_OK)
fDesktop->EventDispatcher().SetTo(gInputManager->GetStream());
break;
}
case AS_APP_CRASHED:
if (fDesktop->LockAllWindows()) {
if (fWindowListLock.Lock()) {
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
ServerWindow* serverWindow = fWindowList.ItemAt(i);
Window* window = serverWindow->Window();
if (window == NULL || window->IsOffscreenWindow())
continue;
if (window->Feel() == kWindowScreenFeel)
fDesktop->SetWindowFeel(window, B_NORMAL_WINDOW_FEEL);
}
fWindowListLock.Unlock();
}
fDesktop->UnlockAllWindows();
}
break;
case AS_DUMP_ALLOCATOR:
fMemoryAllocator->Dump();
break;
case AS_DUMP_BITMAPS:
{
fMapLocker.Lock();
debug_printf("Application %" B_PRId32 ", %s: %d bitmaps:\n",
ClientTeam(), Signature(), (int)fBitmapMap.size());
BitmapMap::const_iterator iterator = fBitmapMap.begin();
for (; iterator != fBitmapMap.end(); iterator++) {
ServerBitmap* bitmap = iterator->second;
debug_printf(" [%" B_PRId32 "] %" B_PRId32 "x%" B_PRId32 ", "
"area %" B_PRId32 ", size %" B_PRId32 "\n",
bitmap->Token(), bitmap->Width(), bitmap->Height(),
bitmap->Area(), bitmap->BitsLength());
}
fMapLocker.Unlock();
break;
}
case AS_CREATE_WINDOW:
case AS_CREATE_OFFSCREEN_WINDOW:
{
port_id clientReplyPort = -1;
status_t status = _CreateWindow(code, link, clientReplyPort);
if (status < B_OK) {
BPrivate::LinkSender reply(clientReplyPort);
reply.StartMessage(status);
reply.Flush();
}
break;
}
case AS_GET_WINDOW_LIST:
{
team_id team;
if (link.Read<team_id>(&team) == B_OK)
fDesktop->WriteWindowList(team, fLink.Sender());
break;
}
case AS_GET_WINDOW_INFO:
{
int32 serverToken;
if (link.Read<int32>(&serverToken) == B_OK)
fDesktop->WriteWindowInfo(serverToken, fLink.Sender());
break;
}
case AS_GET_WINDOW_ORDER:
{
int32 workspace;
if (link.Read<int32>(&workspace) == B_OK)
fDesktop->WriteWindowOrder(workspace, fLink.Sender());
break;
}
case AS_GET_APPLICATION_ORDER:
{
int32 workspace;
if (link.Read<int32>(&workspace) == B_OK)
fDesktop->WriteApplicationOrder(workspace, fLink.Sender());
break;
}
case AS_MINIMIZE_TEAM:
{
team_id team;
if (link.Read<team_id>(&team) == B_OK)
fDesktop->MinimizeApplication(team);
break;
}
case AS_BRING_TEAM_TO_FRONT:
{
team_id team;
if (link.Read<team_id>(&team) == B_OK)
fDesktop->BringApplicationToFront(team);
break;
}
case AS_WINDOW_ACTION:
{
int32 token;
int32 action;
link.Read<int32>(&token);
if (link.Read<int32>(&action) != B_OK)
break;
fDesktop->WindowAction(token, action);
break;
}
case AS_SET_DECORATOR:
{
BString path;
link.ReadString(path);
status_t error = gDecorManager.SetDecorator(path, fDesktop);
fLink.StartMessage(error);
fLink.Flush();
if (error == B_OK)
fDesktop->BroadcastToAllApps(AS_UPDATE_DECORATOR);
break;
}
case AS_GET_DECORATOR:
{
fLink.StartMessage(B_OK);
fLink.AttachString(gDecorManager.GetCurrentDecorator().String());
fLink.Flush();
break;
}
case AS_SET_CONTROL_LOOK:
{
STRACE(("ServerApp %s: Set ControlLook\n", Signature()));
BString path;
status_t error = B_ERROR;
if (link.ReadString(path) == B_OK) {
LockedDesktopSettings settings(fDesktop);
error = settings.SetControlLook(path.String());
}
fLink.StartMessage(error);
fLink.Flush();
break;
}
case AS_GET_CONTROL_LOOK:
{
STRACE(("ServerApp %s: Get ControlLook\n", Signature()));
if (fDesktop->LockSingleWindow()) {
DesktopSettings settings(fDesktop);
fLink.StartMessage(B_OK);
fLink.AttachString(settings.ControlLook().String());
fDesktop->UnlockSingleWindow();
} else
fLink.StartMessage(B_ERROR);
fLink.Flush();
break;
}
case AS_CREATE_BITMAP:
{
STRACE(("ServerApp %s: Received BBitmap creation request\n",
Signature()));
BReference<ServerBitmap> bitmap;
uint8 allocationFlags = kAllocator;
BRect frame;
color_space colorSpace;
uint32 flags;
int32 bytesPerRow;
int32 screenID;
link.Read<BRect>(&frame);
link.Read<color_space>(&colorSpace);
link.Read<uint32>(&flags);
link.Read<int32>(&bytesPerRow);
if (link.Read<int32>(&screenID) == B_OK) {
bitmap.SetTo(gBitmapManager->CreateBitmap(fMemoryAllocator,
*fDesktop->HWInterface(), frame, colorSpace, flags,
bytesPerRow, screenID, &allocationFlags), true);
}
STRACE(("ServerApp %s: Create Bitmap (%.1fx%.1f)\n",
Signature(), frame.Width() + 1, frame.Height() + 1));
if (bitmap != NULL && _AddBitmap(bitmap)) {
fLink.StartMessage(B_OK);
fLink.Attach<int32>(bitmap->Token());
fLink.Attach<uint8>(allocationFlags);
fLink.Attach<area_id>(bitmap->Area());
fLink.Attach<int32>(bitmap->AreaOffset());
if ((allocationFlags & kFramebuffer) != 0)
fLink.Attach<int32>(bitmap->BytesPerRow());
} else {
fLink.StartMessage(B_NO_MEMORY);
}
fLink.Flush();
break;
}
case AS_DELETE_BITMAP:
{
STRACE(("ServerApp %s: received BBitmap delete request\n",
Signature()));
int32 token;
link.Read<int32>(&token);
fMapLocker.Lock();
ServerBitmap* bitmap = _FindBitmap(token);
if (bitmap != NULL) {
STRACE(("ServerApp %s: Deleting Bitmap %" B_PRId32 "\n",
Signature(), token));
_DeleteBitmap(bitmap);
}
fMapLocker.Unlock();
break;
}
case AS_GET_BITMAP_OVERLAY_RESTRICTIONS:
{
overlay_restrictions restrictions;
status_t status = B_ERROR;
int32 token;
if (link.Read<int32>(&token) != B_OK)
break;
BReference<ServerBitmap> bitmap(GetBitmap(token), true);
if (bitmap != NULL) {
STRACE(("ServerApp %s: Get overlay restrictions for bitmap "
"%" B_PRId32 "\n", Signature(), token));
status = fDesktop->HWInterface()->GetOverlayRestrictions(
bitmap->Overlay(), &restrictions);
}
fLink.StartMessage(status);
if (status == B_OK)
fLink.Attach(&restrictions, sizeof(overlay_restrictions));
fLink.Flush();
break;
}
case AS_GET_BITMAP_SUPPORT_FLAGS:
{
uint32 colorSpace;
if (link.Read<uint32>(&colorSpace) != B_OK)
break;
bool overlay = fDesktop->HWInterface()->CheckOverlayRestrictions(
64, 64, (color_space)colorSpace);
uint32 flags = overlay ? B_BITMAPS_SUPPORT_OVERLAY : 0;
fLink.StartMessage(B_OK);
fLink.Attach<int32>(flags);
fLink.Flush();
break;
}
case AS_RECONNECT_BITMAP:
{
BReference<ServerBitmap> bitmap;
BRect frame;
color_space colorSpace;
uint32 flags;
int32 bytesPerRow;
int32 screenID;
area_id clientArea;
int32 areaOffset;
link.Read<BRect>(&frame);
link.Read<color_space>(&colorSpace);
link.Read<uint32>(&flags);
link.Read<int32>(&bytesPerRow);
link.Read<int32>(&screenID);
link.Read<int32>(&clientArea);
if (link.Read<int32>(&areaOffset) == B_OK) {
bitmap.SetTo(gBitmapManager->CloneFromClient(clientArea, areaOffset,
frame, colorSpace, flags, bytesPerRow), true);
}
if (bitmap != NULL && _AddBitmap(bitmap)) {
fLink.StartMessage(B_OK);
fLink.Attach<int32>(bitmap->Token());
fLink.Attach<area_id>(bitmap->Area());
} else {
fLink.StartMessage(B_NO_MEMORY);
}
fLink.Flush();
break;
}
case AS_CREATE_PICTURE:
{
STRACE(("ServerApp %s: Create Picture\n", Signature()));
status_t status = B_NO_MEMORY;
BReference<ServerPicture> picture(CreatePicture());
if (picture != NULL) {
int32 subPicturesCount = 0;
link.Read<int32>(&subPicturesCount);
for (int32 i = 0; i < subPicturesCount; i++) {
int32 token = -1;
link.Read<int32>(&token);
BAutolock _(fMapLocker);
if (ServerPicture* subPicture = _FindPicture(token))
picture->NestPicture(subPicture);
}
status = picture->ImportData(link);
}
if (status == B_OK) {
fLink.StartMessage(B_OK);
fLink.Attach<int32>(picture->Token());
} else
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_DELETE_PICTURE:
{
STRACE(("ServerApp %s: Delete Picture\n", Signature()));
int32 token;
if (link.Read<int32>(&token) == B_OK) {
BAutolock _(fMapLocker);
ServerPicture* picture = _FindPicture(token);
if (picture != NULL)
picture->SetOwner(NULL);
}
break;
}
case AS_CLONE_PICTURE:
{
STRACE(("ServerApp %s: Clone Picture\n", Signature()));
int32 token;
BReference<ServerPicture> original;
if (link.Read<int32>(&token) == B_OK)
original.SetTo(GetPicture(token), true);
if (original != NULL) {
BReference<ServerPicture> cloned(CreatePicture(original), true);
if (cloned != NULL) {
fLink.StartMessage(B_OK);
fLink.Attach<int32>(cloned->Token());
} else
fLink.StartMessage(B_NO_MEMORY);
} else
fLink.StartMessage(B_BAD_VALUE);
fLink.Flush();
break;
}
case AS_DOWNLOAD_PICTURE:
{
STRACE(("ServerApp %s: Download Picture\n", Signature()));
int32 token;
link.Read<int32>(&token);
BReference<ServerPicture> picture(GetPicture(token), true);
if (picture != NULL) {
picture->ExportData(fLink);
} else
fLink.StartMessage(B_ERROR);
fLink.Flush();
break;
}
case AS_CURRENT_WORKSPACE:
STRACE(("ServerApp %s: get current workspace\n", Signature()));
if (fDesktop->LockSingleWindow()) {
fLink.StartMessage(B_OK);
fLink.Attach<int32>(fDesktop->CurrentWorkspace());
fDesktop->UnlockSingleWindow();
} else
fLink.StartMessage(B_ERROR);
fLink.Flush();
break;
case AS_ACTIVATE_WORKSPACE:
{
STRACE(("ServerApp %s: activate workspace\n", Signature()));
int32 index;
link.Read<int32>(&index);
bool takeFocusWindowThere;
link.Read<bool>(&takeFocusWindowThere);
fDesktop->SetWorkspace(index, takeFocusWindowThere);
break;
}
case AS_SET_WORKSPACE_LAYOUT:
{
int32 newColumns;
int32 newRows;
if (link.Read<int32>(&newColumns) == B_OK
&& link.Read<int32>(&newRows) == B_OK)
fDesktop->SetWorkspacesLayout(newColumns, newRows);
break;
}
case AS_GET_WORKSPACE_LAYOUT:
{
if (fDesktop->LockSingleWindow()) {
DesktopSettings settings(fDesktop);
fLink.StartMessage(B_OK);
fLink.Attach<int32>(settings.WorkspacesColumns());
fLink.Attach<int32>(settings.WorkspacesRows());
fDesktop->UnlockSingleWindow();
} else
fLink.StartMessage(B_ERROR);
fLink.Flush();
break;
}
case AS_IDLE_TIME:
STRACE(("ServerApp %s: idle time\n", Signature()));
fLink.StartMessage(B_OK);
fLink.Attach<bigtime_t>(fDesktop->EventDispatcher().IdleTime());
fLink.Flush();
break;
case AS_SHOW_CURSOR:
{
STRACE(("ServerApp %s: Show Cursor\n", Signature()));
fCursorHideLevel--;
if (fCursorHideLevel < 0)
fCursorHideLevel = 0;
fDesktop->HWInterface()->SetCursorVisible(fCursorHideLevel == 0);
break;
}
case AS_HIDE_CURSOR:
{
STRACE(("ServerApp %s: Hide Cursor\n", Signature()));
fCursorHideLevel++;
fDesktop->HWInterface()->SetCursorVisible(fCursorHideLevel == 0);
break;
}
case AS_OBSCURE_CURSOR:
{
STRACE(("ServerApp %s: Obscure Cursor\n", Signature()));
fDesktop->HWInterface()->ObscureCursor();
break;
}
case AS_QUERY_CURSOR_HIDDEN:
{
STRACE(("ServerApp %s: Received IsCursorHidden request\n",
Signature()));
fLink.StartMessage(fCursorHideLevel > 0 ? B_OK : B_ERROR);
fLink.Flush();
break;
}
case AS_SET_CURSOR:
{
STRACE(("ServerApp %s: SetCursor\n", Signature()));
bool sync;
int32 token;
link.Read<bool>(&sync);
if (link.Read<int32>(&token) != B_OK)
break;
if (!fDesktop->GetCursorManager().Lock())
break;
fAppCursor.SetTo(fDesktop->GetCursorManager().FindCursor(token), false);
if (_HasWindowUnderMouse())
fDesktop->SetCursor(CurrentCursor());
fDesktop->GetCursorManager().Unlock();
if (sync) {
fLink.StartMessage(B_OK);
fLink.Flush();
}
break;
}
case AS_SET_VIEW_CURSOR:
{
STRACE(("ServerApp %s: AS_SET_VIEW_CURSOR:\n", Signature()));
ViewSetViewCursorInfo info;
if (link.Read<ViewSetViewCursorInfo>(&info) != B_OK)
break;
if (fDesktop->GetCursorManager().Lock()) {
BReference<ServerCursor> cursor(fDesktop->GetCursorManager().FindCursor(
info.cursorToken), false);
fDesktop->GetCursorManager().Unlock();
fDesktop->LockAllWindows();
View* view;
if (fViewTokens.GetToken(info.viewToken, B_HANDLER_TOKEN,
(void**)&view) == B_OK) {
view->SetCursor(cursor);
Window* window = view->Window();
if (window != NULL && window->IsFocus()) {
if (fDesktop->ViewUnderMouse(window) == view->Token())
SetCurrentCursor(cursor);
}
}
fDesktop->UnlockAllWindows();
}
if (info.sync) {
fLink.StartMessage(B_OK);
fLink.Flush();
}
break;
}
case AS_CREATE_CURSOR:
{
STRACE(("ServerApp %s: Create Cursor\n", Signature()));
status_t status = B_ERROR;
uint8 cursorData[68];
ServerCursor* cursor = NULL;
if (link.Read(cursorData, sizeof(cursorData)) >= B_OK) {
cursor = fDesktop->GetCursorManager().CreateCursor(fClientTeam,
cursorData);
if (cursor == NULL)
status = B_NO_MEMORY;
}
if (cursor != NULL) {
fLink.StartMessage(B_OK);
fLink.Attach<int32>(cursor->Token());
} else
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_CREATE_CURSOR_BITMAP:
{
STRACE(("ServerApp %s: Create Cursor bitmap\n", Signature()));
status_t status = B_ERROR;
int32 size = 0, bytesPerRow = 0;
BRect cursorRect;
color_space colorspace = B_RGBA32;
BPoint hotspot;
ServerCursor* cursor = NULL;
if (link.Read<BRect>(&cursorRect) == B_OK
&& link.Read<BPoint>(&hotspot) == B_OK
&& link.Read<color_space>(&colorspace) == B_OK
&& link.Read<int32>(&bytesPerRow) == B_OK
&& link.Read<int32>(&size) == B_OK
&& size > 0) {
BStackOrHeapArray<uint8, 256> byteArray(size);
if (!byteArray.IsValid()) {
status = B_NO_MEMORY;
} else if (link.Read(byteArray, size) == B_OK) {
cursor = fDesktop->GetCursorManager().CreateCursor(
fClientTeam, cursorRect, colorspace, 0, hotspot);
if (cursor == NULL)
status = B_NO_MEMORY;
else
cursor->ImportBits(byteArray, size, bytesPerRow, colorspace);
}
}
if (cursor != NULL) {
fLink.StartMessage(B_OK);
fLink.Attach<int32>(cursor->Token());
} else
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_CLONE_CURSOR:
{
STRACE(("ServerApp %s: Reference BCursor\n", Signature()));
int32 token;
if (link.Read<int32>(&token) != B_OK)
break;
status_t status = B_ERROR;
ServerCursor* cursor = NULL;
if (fDesktop->GetCursorManager().Lock()) {
ServerCursor* existingCursor
= fDesktop->GetCursorManager().FindCursor(token);
if (existingCursor != NULL)
cursor = new(std::nothrow) ServerCursor(existingCursor);
if (cursor != NULL) {
cursor->SetOwningTeam(fClientTeam);
token = fDesktop->GetCursorManager().AddCursor(cursor);
if (token < 0) {
delete cursor;
cursor = NULL;
}
}
fDesktop->GetCursorManager().Unlock();
}
if (cursor != NULL) {
fLink.StartMessage(B_OK);
fLink.Attach<int32>(cursor->Token());
} else
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_DELETE_CURSOR:
{
STRACE(("ServerApp %s: Delete BCursor\n", Signature()));
int32 token;
if (link.Read<int32>(&token) != B_OK)
break;
if (!fDesktop->GetCursorManager().Lock())
break;
ServerCursor* cursor
= fDesktop->GetCursorManager().FindCursor(token);
if (cursor != NULL && cursor->OwningTeam() == fClientTeam)
fDesktop->GetCursorManager().RemoveCursor(cursor);
fDesktop->GetCursorManager().Unlock();
break;
}
case AS_GET_CURSOR_POSITION:
{
STRACE(("ServerApp %s: Get Cursor position\n", Signature()));
BPoint where;
int32 buttons;
fDesktop->GetLastMouseState(&where, &buttons);
fLink.StartMessage(B_OK);
fLink.Attach<BPoint>(where);
fLink.Attach<int32>(buttons);
fLink.Flush();
break;
}
case AS_GET_CURSOR_BITMAP:
{
STRACE(("ServerApp %s: Get Cursor bitmap\n", Signature()));
ServerCursorReference cursorRef = fDesktop->Cursor();
ServerCursor* cursor = cursorRef.Get();
if (cursor != NULL) {
uint32 size = cursor->BitsLength();
fLink.StartMessage(B_OK);
fLink.Attach<uint32>(size);
fLink.Attach<uint32>(cursor->Width());
fLink.Attach<uint32>(cursor->Height());
fLink.Attach<color_space>(cursor->ColorSpace());
fLink.Attach<BPoint>(cursor->GetHotSpot());
fLink.Attach(cursor->Bits(), size);
} else
fLink.StartMessage(B_ERROR);
fLink.Flush();
break;
}
case AS_GET_SCROLLBAR_INFO:
{
STRACE(("ServerApp %s: Get ScrollBar info\n", Signature()));
if (fDesktop->LockSingleWindow()) {
scroll_bar_info info;
DesktopSettings settings(fDesktop);
settings.GetScrollBarInfo(info);
fLink.StartMessage(B_OK);
fLink.Attach<scroll_bar_info>(info);
fDesktop->UnlockSingleWindow();
} else
fLink.StartMessage(B_ERROR);
fLink.Flush();
break;
}
case AS_SET_SCROLLBAR_INFO:
{
STRACE(("ServerApp %s: Set ScrollBar info\n", Signature()));
scroll_bar_info info;
if (link.Read<scroll_bar_info>(&info) == B_OK) {
LockedDesktopSettings settings(fDesktop);
settings.SetScrollBarInfo(info);
}
fLink.StartMessage(B_OK);
fLink.Flush();
break;
}
case AS_GET_MENU_INFO:
{
STRACE(("ServerApp %s: Get menu info\n", Signature()));
if (fDesktop->LockSingleWindow()) {
menu_info info;
DesktopSettings settings(fDesktop);
settings.GetMenuInfo(info);
fLink.StartMessage(B_OK);
fLink.Attach<menu_info>(info);
fDesktop->UnlockSingleWindow();
} else
fLink.StartMessage(B_ERROR);
fLink.Flush();
break;
}
case AS_SET_MENU_INFO:
{
STRACE(("ServerApp %s: Set menu info\n", Signature()));
menu_info info;
if (link.Read<menu_info>(&info) == B_OK) {
LockedDesktopSettings settings(fDesktop);
settings.SetMenuInfo(info);
}
fLink.StartMessage(B_OK);
fLink.Flush();
break;
}
case AS_SET_MOUSE_MODE:
{
STRACE(("ServerApp %s: Set Mouse Focus mode\n",
Signature()));
mode_mouse mouseMode;
if (link.Read<mode_mouse>(&mouseMode) == B_OK) {
LockedDesktopSettings settings(fDesktop);
settings.SetMouseMode(mouseMode);
}
break;
}
case AS_GET_MOUSE_MODE:
{
STRACE(("ServerApp %s: Get Mouse Focus mode\n",
Signature()));
if (fDesktop->LockSingleWindow()) {
DesktopSettings settings(fDesktop);
fLink.StartMessage(B_OK);
fLink.Attach<mode_mouse>(settings.MouseMode());
fDesktop->UnlockSingleWindow();
} else
fLink.StartMessage(B_ERROR);
fLink.Flush();
break;
}
case AS_SET_FOCUS_FOLLOWS_MOUSE_MODE:
{
STRACE(("ServerApp %s: Set Focus Follows Mouse mode\n", Signature()));
mode_focus_follows_mouse focusFollowsMousMode;
if (link.Read<mode_focus_follows_mouse>(&focusFollowsMousMode) == B_OK) {
LockedDesktopSettings settings(fDesktop);
settings.SetFocusFollowsMouseMode(focusFollowsMousMode);
}
break;
}
case AS_GET_FOCUS_FOLLOWS_MOUSE_MODE:
{
STRACE(("ServerApp %s: Get Focus Follows Mouse mode\n", Signature()));
if (fDesktop->LockSingleWindow()) {
DesktopSettings settings(fDesktop);
fLink.StartMessage(B_OK);
fLink.Attach<mode_focus_follows_mouse>(
settings.FocusFollowsMouseMode());
fDesktop->UnlockSingleWindow();
} else
fLink.StartMessage(B_ERROR);
fLink.Flush();
break;
}
case AS_SET_ACCEPT_FIRST_CLICK:
{
STRACE(("ServerApp %s: Set Accept First Click\n", Signature()));
bool acceptFirstClick;
if (link.Read<bool>(&acceptFirstClick) == B_OK) {
LockedDesktopSettings settings(fDesktop);
settings.SetAcceptFirstClick(acceptFirstClick);
}
break;
}
case AS_GET_ACCEPT_FIRST_CLICK:
{
STRACE(("ServerApp %s: Get Accept First Click\n", Signature()));
if (fDesktop->LockSingleWindow()) {
DesktopSettings settings(fDesktop);
fLink.StartMessage(B_OK);
fLink.Attach<bool>(settings.AcceptFirstClick());
fDesktop->UnlockSingleWindow();
} else
fLink.StartMessage(B_ERROR);
fLink.Flush();
break;
}
case AS_GET_SHOW_ALL_DRAGGERS:
{
STRACE(("ServerApp %s: Get Show All Draggers\n", Signature()));
if (fDesktop->LockSingleWindow()) {
DesktopSettings settings(fDesktop);
fLink.StartMessage(B_OK);
fLink.Attach<bool>(settings.ShowAllDraggers());
fDesktop->UnlockSingleWindow();
} else
fLink.StartMessage(B_ERROR);
fLink.Flush();
break;
}
case AS_SET_SHOW_ALL_DRAGGERS:
{
STRACE(("ServerApp %s: Set Show All Draggers\n", Signature()));
bool changed = false;
bool show;
if (link.Read<bool>(&show) == B_OK) {
LockedDesktopSettings settings(fDesktop);
if (show != settings.ShowAllDraggers()) {
settings.SetShowAllDraggers(show);
changed = true;
}
}
if (changed)
fDesktop->BroadcastToAllApps(kMsgUpdateShowAllDraggers);
break;
}
case kMsgUpdateShowAllDraggers:
{
bool show = false;
if (fDesktop->LockSingleWindow()) {
DesktopSettings settings(fDesktop);
show = settings.ShowAllDraggers();
fDesktop->UnlockSingleWindow();
}
BMessage update(_SHOW_DRAG_HANDLES_);
update.AddBool("show", show);
SendMessageToClient(&update);
break;
}
case AS_ADD_FONT_FILE:
{
FTRACE(("ServerApp %s: Received BFont creation request\n",
Signature()));
AutoLocker< ::FontManager> fontLock(fAppFontManager);
if (fAppFontManager->CountFamilies() > MAX_USER_FONTS) {
fLink.StartMessage(B_NOT_ALLOWED);
fLink.Flush();
break;
}
uint16 familyID, styleID;
char* fontPath;
uint16 index, instance;
link.ReadString(&fontPath);
link.Read<uint16>(&index);
link.Read<uint16>(&instance);
status_t status = fAppFontManager->AddUserFontFromFile(fontPath, index, instance,
familyID, styleID);
if (status != B_OK) {
fLink.StartMessage(status);
} else {
ServerFont font;
status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
fLink.StartMessage(status);
if (status == B_OK) {
fLink.Attach<uint16>(font.FamilyID());
fLink.Attach<uint16>(font.StyleID());
fLink.Attach<uint16>(font.Face());
}
}
fLink.Flush();
break;
}
case AS_ADD_FONT_MEMORY:
{
FTRACE(("ServerApp %s: Received BFont memory creation request\n",
Signature()));
AutoLocker< ::FontManager> fontLock(fAppFontManager);
if (fAppFontManager->CountFamilies() > MAX_USER_FONTS) {
fLink.StartMessage(B_NOT_ALLOWED);
fLink.Flush();
break;
}
area_id fontAreaID, fontAreaCloneID;
area_info fontAreaInfo;
char* area_addr;
size_t size, offset;
uint16 index, instance;
link.Read<int32>(&fontAreaID);
link.Read<size_t>(&size);
link.Read<size_t>(&offset);
link.Read<uint16>(&index);
link.Read<uint16>(&instance);
fontAreaCloneID = clone_area("user font",
(void **)&area_addr,
B_ANY_ADDRESS,
B_READ_AREA,
fontAreaID);
if (fontAreaCloneID < B_OK) {
fLink.StartMessage(fontAreaCloneID);
fLink.Flush();
break;
}
status_t status = get_area_info(fontAreaCloneID, &fontAreaInfo);
if (status != B_OK) {
fLink.StartMessage(status);
fLink.Flush();
delete_area(fontAreaCloneID);
break;
}
size_t fontMemorySize = fontAreaInfo.size - offset;
if (size == 0)
size = fontMemorySize;
if (size > MAX_FONT_DATA_SIZE_BYTES
|| size > fontMemorySize) {
fLink.StartMessage(B_BAD_DATA);
fLink.Flush();
delete_area(fontAreaCloneID);
break;
}
FT_Byte* fontData = (FT_Byte*)(malloc (sizeof(FT_Byte) * size));
if (fontData == NULL) {
delete_area(fontAreaCloneID);
fLink.StartMessage(B_BAD_DATA);
fLink.Flush();
break;
}
memcpy(fontData, (FT_Byte*)fontAreaInfo.address + offset, size);
delete_area(fontAreaCloneID);
uint16 familyID, styleID;
status = fAppFontManager->AddUserFontFromMemory(fontData, size, index, instance,
familyID, styleID);
if (status != B_OK) {
fLink.StartMessage(status);
free(fontData);
} else {
ServerFont font;
status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK) {
font.SetFontData(fontData, size);
fLink.StartMessage(B_OK);
fLink.Attach<uint16>(font.FamilyID());
fLink.Attach<uint16>(font.StyleID());
fLink.Attach<uint16>(font.Face());
} else {
fLink.StartMessage(status);
free(fontData);
}
}
fLink.Flush();
break;
}
case AS_REMOVE_FONT:
{
STRACE(("ServerApp %s: Received BFont removal request\n",
Signature()));
uint16 familyID, styleID;
link.Read<uint16>(&familyID);
link.Read<uint16>(&styleID);
status_t status = B_OK;
AutoLocker< ::FontManager> fontLock(fAppFontManager);
status = fAppFontManager->RemoveUserFont(familyID, styleID);
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_SET_SYSTEM_FONT:
{
FTRACE(("ServerApp %s: AS_SET_SYSTEM_FONT\n", Signature()));
char type[B_OS_NAME_LENGTH];
font_family familyName;
font_style styleName;
float size;
if (link.ReadString(type, sizeof(type)) == B_OK
&& link.ReadString(familyName, sizeof(familyName)) == B_OK
&& link.ReadString(styleName, sizeof(styleName)) == B_OK
&& link.Read<float>(&size) == B_OK) {
gFontManager->Lock();
FontStyle* style
= gFontManager->GetStyle(familyName, styleName);
if (style != NULL) {
ServerFont font(*style, size);
gFontManager->Unlock();
LockedDesktopSettings settings(fDesktop);
if (strcmp(type, "plain") == 0)
settings.SetDefaultPlainFont(font);
else if (strcmp(type, "bold") == 0)
settings.SetDefaultBoldFont(font);
else if (strcmp(type, "fixed") == 0)
settings.SetDefaultFixedFont(font);
} else
gFontManager->Unlock();
}
break;
}
case AS_GET_SYSTEM_DEFAULT_FONT:
{
ServerFont font;
char type[B_OS_NAME_LENGTH];
status_t status = link.ReadString(type, sizeof(type));
if (status == B_OK) {
if (strcmp(type, "plain") == 0)
font = *gFontManager->DefaultPlainFont();
else if (strcmp(type, "bold") == 0)
font = *gFontManager->DefaultBoldFont();
else if (strcmp(type, "fixed") == 0)
font = *gFontManager->DefaultFixedFont();
else
status = B_BAD_VALUE;
}
if (status == B_OK) {
fLink.StartMessage(B_OK);
fLink.AttachString(font.Family());
fLink.AttachString(font.Style());
fLink.Attach<float>(font.Size());
} else
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_GET_SYSTEM_FONTS:
{
FTRACE(("ServerApp %s: AS_GET_SYSTEM_FONTS\n", Signature()));
if (!fDesktop->LockSingleWindow()) {
fLink.StartMessage(B_OK);
fLink.Flush();
break;
}
DesktopSettings settings(fDesktop);
settings.GetDefaultPlainFont(fPlainFont);
settings.GetDefaultBoldFont(fBoldFont);
settings.GetDefaultFixedFont(fFixedFont);
fLink.StartMessage(B_OK);
for (int32 i = 0; i < 3; i++) {
ServerFont* font = NULL;
switch (i) {
case 0:
font = &fPlainFont;
fLink.AttachString("plain");
break;
case 1:
font = &fBoldFont;
fLink.AttachString("bold");
break;
case 2:
font = &fFixedFont;
fLink.AttachString("fixed");
break;
}
fLink.Attach<uint16>(font->FamilyID());
fLink.Attach<uint16>(font->StyleID());
fLink.Attach<float>(font->Size());
fLink.Attach<uint16>(font->Face());
fLink.Attach<uint32>(font->Flags());
}
fDesktop->UnlockSingleWindow();
fLink.Flush();
break;
}
case AS_GET_FONT_LIST_REVISION:
{
FTRACE(("ServerApp %s: AS_GET_FONT_LIST_REVISION\n", Signature()));
fLink.StartMessage(B_OK);
gFontManager->Lock();
fLink.Attach<uint32>(gFontManager->Revision());
gFontManager->Unlock();
fLink.Flush();
break;
}
case AS_GET_FAMILY_AND_STYLES:
{
FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLES\n", Signature()));
int32 index;
link.Read<int32>(&index);
AutoLocker< ::FontManager> fontLock(gFontManager);
FontFamily* family = gFontManager->FamilyAt(index);
if (family == NULL) {
fontLock.SetTo(fAppFontManager, false);
family = fAppFontManager->FamilyAt(index);
}
if (family) {
fLink.StartMessage(B_OK);
fLink.AttachString(family->Name());
fLink.Attach<uint32>(family->Flags());
int32 count = family->CountStyles();
fLink.Attach<int32>(count);
for (int32 i = 0; i < count; i++) {
FontStyle* style = family->StyleAt(i);
fLink.AttachString(style->Name());
fLink.Attach<uint16>(style->Face());
fLink.Attach<uint32>(style->Flags());
}
} else
fLink.StartMessage(B_BAD_VALUE);
fLink.Flush();
break;
}
case AS_GET_FAMILY_AND_STYLE:
{
FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLE\n", Signature()));
uint16 familyID, styleID;
link.Read<uint16>(&familyID);
link.Read<uint16>(&styleID);
AutoLocker< ::FontManager> fontLock(gFontManager);
FontStyle* fontStyle = gFontManager->GetStyle(familyID, styleID);
if (fontStyle == NULL) {
fontLock.SetTo(fAppFontManager, false);
fontStyle = fAppFontManager->GetStyle(familyID, styleID);
}
if (fontStyle != NULL) {
fLink.StartMessage(B_OK);
fLink.AttachString(fontStyle->Family()->Name());
fLink.AttachString(fontStyle->Name());
} else
fLink.StartMessage(B_BAD_VALUE);
fLink.Flush();
break;
}
case AS_GET_FAMILY_AND_STYLE_IDS:
{
FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLE_IDS\n",
Signature()));
font_family family;
font_style style;
uint16 familyID, styleID;
uint16 face;
if (link.ReadString(family, sizeof(font_family)) == B_OK
&& link.ReadString(style, sizeof(font_style)) == B_OK
&& link.Read<uint16>(&familyID) == B_OK
&& link.Read<uint16>(&styleID) == B_OK
&& link.Read<uint16>(&face) == B_OK) {
AutoLocker< ::FontManager> fontLock(gFontManager);
FontStyle* fontStyle = gFontManager->GetStyle(family, style,
familyID, styleID, face);
if (fontStyle == NULL) {
fontLock.SetTo(fAppFontManager, false);
fontStyle = fAppFontManager->GetStyle(family, style,
familyID, styleID, face);
}
if (fontStyle != NULL) {
fLink.StartMessage(B_OK);
fLink.Attach<uint16>(fontStyle->Family()->ID());
fLink.Attach<uint16>(fontStyle->ID());
face = fontStyle->PreservedFace(face);
fLink.Attach<uint16>(face);
} else
fLink.StartMessage(B_NAME_NOT_FOUND);
} else
fLink.StartMessage(B_BAD_VALUE);
fLink.Flush();
break;
}
case AS_GET_FONT_FILE_FORMAT:
{
FTRACE(("ServerApp %s: AS_GET_FONT_FILE_FORMAT\n", Signature()));
int32 familyID, styleID;
link.Read<int32>(&familyID);
link.Read<int32>(&styleID);
AutoLocker< ::FontManager> fontLock(gFontManager);
FontStyle* fontStyle = gFontManager->GetStyle(familyID, styleID);
if (fontStyle == NULL) {
fontLock.SetTo(fAppFontManager, false);
fontStyle = fAppFontManager->GetStyle(familyID, styleID);
}
if (fontStyle != NULL) {
fLink.StartMessage(B_OK);
fLink.Attach<uint16>((uint16)fontStyle->FileFormat());
} else
fLink.StartMessage(B_BAD_VALUE);
fLink.Flush();
break;
}
case AS_GET_STRING_WIDTHS:
{
FTRACE(("ServerApp %s: AS_GET_STRING_WIDTHS\n", Signature()));
uint16 familyID, styleID;
float size;
uint8 spacing;
link.Read<uint16>(&familyID);
link.Read<uint16>(&styleID);
link.Read<float>(&size);
link.Read<uint8>(&spacing);
int32 numStrings;
if (link.Read<int32>(&numStrings) != B_OK) {
numStrings = 0;
size = 0.0f;
}
BStackOrHeapArray<float, 64> widthArray(numStrings);
BStackOrHeapArray<int32, 64> lengthArray(numStrings);
BStackOrHeapArray<char*, 64> stringArray(numStrings);
if (!widthArray.IsValid() || !lengthArray.IsValid()
|| !stringArray.IsValid()) {
fLink.StartMessage(B_NO_MEMORY);
fLink.Flush();
break;
}
for (int32 i = 0; i < numStrings; i++) {
link.ReadString(&stringArray[i], (size_t *)&lengthArray[i]);
}
ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK && size > 0) {
font.SetSize(size);
font.SetSpacing(spacing);
for (int32 i = 0; i < numStrings; i++) {
if (!stringArray[i] || lengthArray[i] <= 0)
widthArray[i] = 0.0;
else {
widthArray[i] = font.StringWidth(stringArray[i],
lengthArray[i]);
}
}
fLink.StartMessage(B_OK);
fLink.Attach(widthArray, numStrings * sizeof(float));
} else
fLink.StartMessage(B_BAD_VALUE);
fLink.Flush();
for (int32 i = 0; i < numStrings; i++)
free(stringArray[i]);
break;
}
case AS_GET_FONT_BOUNDING_BOX:
{
FTRACE(("ServerApp %s: AS_GET_BOUNDING_BOX\n",
Signature()));
uint16 familyID, styleID;
float size;
link.Read<uint16>(&familyID);
link.Read<uint16>(&styleID);
link.Read<float>(&size);
ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK && size > 0) {
font.SetSize(size);
fLink.StartMessage(B_OK);
fLink.Attach<BRect>(font.BoundingBox());
} else
fLink.StartMessage(B_BAD_VALUE);
fLink.Flush();
break;
}
case AS_GET_TUNED_COUNT:
{
FTRACE(("ServerApp %s: AS_GET_TUNED_COUNT\n", Signature()));
uint16 familyID, styleID;
link.Read<uint16>(&familyID);
link.Read<uint16>(&styleID);
AutoLocker< ::FontManager> fontLock(gFontManager);
FontStyle* fontStyle = gFontManager->GetStyle(familyID, styleID);
if (fontStyle == NULL) {
fontLock.SetTo(fAppFontManager, false);
fontStyle = fAppFontManager->GetStyle(familyID, styleID);
}
if (fontStyle != NULL) {
fLink.StartMessage(B_OK);
fLink.Attach<int32>(fontStyle->TunedCount());
} else
fLink.StartMessage(B_BAD_VALUE);
fLink.Flush();
break;
}
case AS_GET_TUNED_INFO:
{
FTRACE(("ServerApp %s: AS_GET_TUNED_INFO unimplmemented\n",
Signature()));
fLink.StartMessage(B_ERROR);
fLink.Flush();
break;
}
case AS_GET_EXTRA_FONT_FLAGS:
{
FTRACE(("ServerApp %s: AS_GET_EXTRA_FONT_FLAGS\n",
Signature()));
uint16 familyID, styleID;
link.Read<uint16>(&familyID);
link.Read<uint16>(&styleID);
AutoLocker< ::FontManager> fontLock(gFontManager);
FontStyle* fontStyle = gFontManager->GetStyle(familyID, styleID);
if (fontStyle == NULL) {
fontLock.SetTo(fAppFontManager, false);
fontStyle = fAppFontManager->GetStyle(familyID, styleID);
}
if (fontStyle != NULL) {
fLink.StartMessage(B_OK);
fLink.Attach<uint32>(fontStyle->Flags());
} else
fLink.StartMessage(B_BAD_VALUE);
fLink.Flush();
break;
}
case AS_GET_FONT_HEIGHT:
{
FTRACE(("ServerApp %s: AS_GET_FONT_HEIGHT\n", Signature()));
uint16 familyID, styleID;
float size;
link.Read<uint16>(&familyID);
link.Read<uint16>(&styleID);
link.Read<float>(&size);
AutoLocker< ::FontManager> fontLock(gFontManager);
FontStyle* fontStyle = gFontManager->GetStyle(familyID, styleID);
if (fontStyle == NULL) {
fontLock.SetTo(fAppFontManager, false);
fontStyle = fAppFontManager->GetStyle(familyID, styleID);
}
if (fontStyle != NULL) {
font_height height;
fontStyle->GetHeight(size, height);
fLink.StartMessage(B_OK);
fLink.Attach<font_height>(height);
} else
fLink.StartMessage(B_BAD_VALUE);
fLink.Flush();
break;
}
case AS_GET_UNICODE_BLOCKS:
{
FTRACE(("ServerApp %s: AS_GET_UNICODE_BLOCKS\n", Signature()));
uint16 familyID, styleID;
link.Read<uint16>(&familyID);
link.Read<uint16>(&styleID);
ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK) {
unicode_block blocksForFont;
font.GetUnicodeBlocks(blocksForFont);
fLink.StartMessage(B_OK);
fLink.Attach<unicode_block>(blocksForFont);
} else
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_GET_HAS_UNICODE_BLOCK:
{
FTRACE(("ServerApp %s: AS_INCLUDES_UNICODE_BLOCK\n", Signature()));
uint16 familyID, styleID;
uint32 start, end;
link.Read<uint16>(&familyID);
link.Read<uint16>(&styleID);
link.Read<uint32>(&start);
link.Read<uint32>(&end);
ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK) {
bool hasBlock;
status = font.IncludesUnicodeBlock(start, end, hasBlock);
fLink.StartMessage(status);
fLink.Attach<bool>(hasBlock);
} else
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_GET_GLYPH_SHAPES:
{
FTRACE(("ServerApp %s: AS_GET_GLYPH_SHAPES\n", Signature()));
uint16 familyID, styleID;
uint32 flags;
float size, shear, rotation, falseBoldWidth;
link.Read<uint16>(&familyID);
link.Read<uint16>(&styleID);
link.Read<float>(&size);
link.Read<float>(&shear);
link.Read<float>(&rotation);
link.Read<float>(&falseBoldWidth);
link.Read<uint32>(&flags);
int32 numChars, numBytes;
link.Read<int32>(&numChars);
link.Read<int32>(&numBytes);
BStackOrHeapArray<char, 256> charArray(numBytes);
BStackOrHeapArray<BShape*, 64> shapes(numChars);
if (!charArray.IsValid() || !shapes.IsValid()) {
fLink.StartMessage(B_NO_MEMORY);
fLink.Flush();
break;
}
link.Read(charArray, numBytes);
ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK) {
font.SetSize(size);
font.SetShear(shear);
font.SetRotation(rotation);
font.SetFalseBoldWidth(falseBoldWidth);
font.SetFlags(flags);
status = font.GetGlyphShapes(charArray, numChars, shapes);
if (status == B_OK) {
fLink.StartMessage(B_OK);
for (int32 i = 0; i < numChars; i++) {
fLink.AttachShape(*shapes[i]);
delete shapes[i];
}
}
}
if (status != B_OK)
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_GET_HAS_GLYPHS:
{
FTRACE(("ServerApp %s: AS_GET_HAS_GLYPHS\n", Signature()));
uint16 familyID, styleID;
link.Read<uint16>(&familyID);
link.Read<uint16>(&styleID);
int32 numChars, numBytes;
link.Read<int32>(&numChars);
link.Read<int32>(&numBytes);
BStackOrHeapArray<char, 256> charArray(numBytes);
BStackOrHeapArray<bool, 256> hasArray(numChars);
if (!charArray.IsValid() || !hasArray.IsValid()) {
fLink.StartMessage(B_NO_MEMORY);
fLink.Flush();
break;
}
link.Read(charArray, numBytes);
bool useFallbacks;
link.Read<bool>(&useFallbacks);
ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK) {
status = font.GetHasGlyphs(charArray, numBytes, numChars, hasArray, useFallbacks);
if (status == B_OK) {
fLink.StartMessage(B_OK);
fLink.Attach(hasArray, numChars * sizeof(bool));
}
}
if (status != B_OK)
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_GET_EDGES:
{
FTRACE(("ServerApp %s: AS_GET_EDGES\n", Signature()));
uint16 familyID, styleID;
link.Read<uint16>(&familyID);
link.Read<uint16>(&styleID);
int32 numChars;
link.Read<int32>(&numChars);
uint32 numBytes;
link.Read<uint32>(&numBytes);
BStackOrHeapArray<char, 256> charArray(numBytes);
BStackOrHeapArray<edge_info, 64> edgeArray(numChars);
if (!charArray.IsValid() || !edgeArray.IsValid()) {
fLink.StartMessage(B_NO_MEMORY);
fLink.Flush();
break;
}
link.Read(charArray, numBytes);
ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK) {
status = font.GetEdges(charArray, numBytes, numChars,
edgeArray);
if (status == B_OK) {
fLink.StartMessage(B_OK);
fLink.Attach(edgeArray, numChars * sizeof(edge_info));
}
}
if (status != B_OK)
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_GET_ESCAPEMENTS:
{
FTRACE(("ServerApp %s: AS_GET_ESCAPEMENTS\n", Signature()));
uint16 familyID, styleID;
uint32 flags;
float size, rotation;
uint8 spacing;
link.Read<uint16>(&familyID);
link.Read<uint16>(&styleID);
link.Read<float>(&size);
link.Read<uint8>(&spacing);
link.Read<float>(&rotation);
link.Read<uint32>(&flags);
escapement_delta delta;
link.Read<float>(&delta.nonspace);
link.Read<float>(&delta.space);
bool wantsOffsets;
link.Read<bool>(&wantsOffsets);
int32 numChars;
link.Read<int32>(&numChars);
uint32 numBytes;
link.Read<uint32>(&numBytes);
BStackOrHeapArray<char, 256> charArray(numBytes);
BStackOrHeapArray<BPoint, 64> escapements(numChars);
BPoint* offsets = NULL;
if (wantsOffsets)
offsets = new(std::nothrow) BPoint[numChars];
if (!charArray.IsValid() || !escapements.IsValid()
|| (offsets == NULL && wantsOffsets)) {
delete[] offsets;
fLink.StartMessage(B_NO_MEMORY);
fLink.Flush();
break;
}
link.Read(charArray, numBytes);
ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK) {
font.SetSize(size);
font.SetSpacing(spacing);
font.SetRotation(rotation);
font.SetFlags(flags);
status = font.GetEscapements(charArray, numBytes, numChars,
delta, escapements, offsets);
if (status == B_OK) {
fLink.StartMessage(B_OK);
for (int32 i = 0; i < numChars; i++)
fLink.Attach<BPoint>(escapements[i]);
if (wantsOffsets) {
for (int32 i = 0; i < numChars; i++)
fLink.Attach<BPoint>(offsets[i]);
}
}
}
if (status != B_OK)
fLink.StartMessage(status);
delete[] offsets;
fLink.Flush();
break;
}
case AS_GET_ESCAPEMENTS_AS_FLOATS:
{
FTRACE(("ServerApp %s: AS_GET_ESCAPEMENTS_AS_FLOATS\n", Signature()));
uint16 familyID, styleID;
uint32 flags;
float size, rotation;
uint8 spacing;
link.Read<uint16>(&familyID);
link.Read<uint16>(&styleID);
link.Read<float>(&size);
link.Read<uint8>(&spacing);
link.Read<float>(&rotation);
link.Read<uint32>(&flags);
escapement_delta delta;
link.Read<float>(&delta.nonspace);
link.Read<float>(&delta.space);
int32 numChars;
link.Read<int32>(&numChars);
uint32 numBytes;
link.Read<uint32>(&numBytes);
BStackOrHeapArray<char, 256> charArray(numBytes);
BStackOrHeapArray<float, 64> escapements(numChars);
if (!charArray.IsValid() || !escapements.IsValid()) {
fLink.StartMessage(B_NO_MEMORY);
fLink.Flush();
break;
}
link.Read(charArray, numBytes);
ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK) {
font.SetSize(size);
font.SetSpacing(spacing);
font.SetRotation(rotation);
font.SetFlags(flags);
status = font.GetEscapements(charArray, numBytes, numChars,
delta, escapements);
if (status == B_OK) {
fLink.StartMessage(B_OK);
fLink.Attach(escapements, numChars * sizeof(float));
}
}
if (status != B_OK)
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_GET_BOUNDINGBOXES_CHARS:
case AS_GET_BOUNDINGBOXES_STRING:
{
FTRACE(("ServerApp %s: AS_GET_BOUNDINGBOXES_CHARS\n", Signature()));
uint16 familyID, styleID;
uint32 flags;
float size, rotation, shear, falseBoldWidth;
uint8 spacing;
font_metric_mode mode;
bool stringEscapement;
link.Read<uint16>(&familyID);
link.Read<uint16>(&styleID);
link.Read<float>(&size);
link.Read<float>(&rotation);
link.Read<float>(&shear);
link.Read<float>(&falseBoldWidth);
link.Read<uint8>(&spacing);
link.Read<uint32>(&flags);
link.Read<font_metric_mode>(&mode);
link.Read<bool>(&stringEscapement);
escapement_delta delta;
link.Read<escapement_delta>(&delta);
int32 numChars;
link.Read<int32>(&numChars);
uint32 numBytes;
link.Read<uint32>(&numBytes);
BStackOrHeapArray<char, 256> charArray(numBytes);
BStackOrHeapArray<BRect, 64> rectArray(numChars);
if (!charArray.IsValid() || !rectArray.IsValid()) {
fLink.StartMessage(B_NO_MEMORY);
fLink.Flush();
break;
}
link.Read(charArray, numBytes);
ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK) {
font.SetSize(size);
font.SetRotation(rotation);
font.SetShear(shear);
font.SetFalseBoldWidth(falseBoldWidth);
font.SetSpacing(spacing);
font.SetFlags(flags);
status = font.GetBoundingBoxes(charArray, numBytes,
numChars, rectArray, stringEscapement, mode, delta,
code == AS_GET_BOUNDINGBOXES_STRING);
if (status == B_OK) {
fLink.StartMessage(B_OK);
for (int32 i = 0; i < numChars; i++)
fLink.Attach<BRect>(rectArray[i]);
}
}
if (status != B_OK)
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_GET_BOUNDINGBOXES_STRINGS:
{
FTRACE(("ServerApp %s: AS_GET_BOUNDINGBOXES_STRINGS\n",
Signature()));
uint16 familyID, styleID;
uint32 flags;
float ptsize, rotation, shear, falseBoldWidth;
uint8 spacing;
font_metric_mode mode;
link.Read<uint16>(&familyID);
link.Read<uint16>(&styleID);
link.Read<float>(&ptsize);
link.Read<float>(&rotation);
link.Read<float>(&shear);
link.Read<float>(&falseBoldWidth);
link.Read<uint8>(&spacing);
link.Read<uint32>(&flags);
link.Read<font_metric_mode>(&mode);
int32 numStrings;
link.Read<int32>(&numStrings);
BStackOrHeapArray<escapement_delta, 64> deltaArray(numStrings);
BStackOrHeapArray<char*, 64> stringArray(numStrings);
BStackOrHeapArray<size_t, 64> lengthArray(numStrings);
BStackOrHeapArray<BRect, 64> rectArray(numStrings);
if (!deltaArray.IsValid() || !stringArray.IsValid()
|| !lengthArray.IsValid() || !rectArray.IsValid()) {
fLink.StartMessage(B_NO_MEMORY);
fLink.Flush();
break;
}
for (int32 i = 0; i < numStrings; i++) {
link.ReadString(&stringArray[i], &lengthArray[i]);
link.Read<escapement_delta>(&deltaArray[i]);
}
ServerFont font;
status_t status = font.SetFamilyAndStyle(familyID, styleID,
fAppFontManager);
if (status == B_OK) {
font.SetSize(ptsize);
font.SetRotation(rotation);
font.SetShear(shear);
font.SetFalseBoldWidth(falseBoldWidth);
font.SetSpacing(spacing);
font.SetFlags(flags);
status = font.GetBoundingBoxesForStrings(stringArray,
lengthArray, numStrings, rectArray, mode, deltaArray);
if (status == B_OK) {
fLink.StartMessage(B_OK);
fLink.Attach(rectArray, numStrings * sizeof(BRect));
}
}
for (int32 i = 0; i < numStrings; i++)
free(stringArray[i]);
if (status != B_OK)
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_VALID_SCREEN_ID:
{
int32 id;
if (link.Read<int32>(&id) == B_OK
&& id == B_MAIN_SCREEN_ID.id)
fLink.StartMessage(B_OK);
else
fLink.StartMessage(B_ERROR);
fLink.Flush();
break;
}
case AS_GET_NEXT_SCREEN_ID:
{
int32 id;
link.Read<int32>(&id);
fLink.StartMessage(B_ENTRY_NOT_FOUND);
fLink.Flush();
break;
}
case AS_GET_SCREEN_ID_FROM_WINDOW:
{
status_t status = B_BAD_VALUE;
int32 clientToken;
if (link.Read<int32>(&clientToken) != B_OK)
status = B_BAD_DATA;
else {
BAutolock locker(fWindowListLock);
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
ServerWindow* serverWindow = fWindowList.ItemAt(i);
if (serverWindow->ClientToken() == clientToken) {
AutoReadLocker _(fDesktop->ScreenLocker());
Window* window = serverWindow->Window();
const Screen* screen = NULL;
if (window != NULL)
screen = window->Screen();
if (screen == NULL) {
break;
}
fLink.StartMessage(B_OK);
fLink.Attach<int32>(screen->ID());
status = B_OK;
break;
}
}
}
if (status != B_OK)
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_SCREEN_GET_MODE:
{
STRACE(("ServerApp %s: AS_SCREEN_GET_MODE\n", Signature()));
int32 id;
link.Read<int32>(&id);
uint32 workspace;
link.Read<uint32>(&workspace);
display_mode mode;
status_t status = fDesktop->GetScreenMode(workspace, id, mode);
fLink.StartMessage(status);
if (status == B_OK)
fLink.Attach<display_mode>(mode);
fLink.Flush();
break;
}
case AS_SCREEN_SET_MODE:
{
STRACE(("ServerApp %s: AS_SCREEN_SET_MODE\n", Signature()));
int32 id;
link.Read<int32>(&id);
uint32 workspace;
link.Read<uint32>(&workspace);
display_mode mode;
link.Read<display_mode>(&mode);
bool makeDefault = false;
status_t status = link.Read<bool>(&makeDefault);
if (status == B_OK) {
status = fDesktop->SetScreenMode(workspace, id, mode,
makeDefault);
}
if (status == B_OK) {
if (workspace == (uint32)B_CURRENT_WORKSPACE_INDEX
&& fDesktop->LockSingleWindow()) {
workspace = fDesktop->CurrentWorkspace();
fDesktop->UnlockSingleWindow();
}
if (!makeDefault) {
fTemporaryDisplayModeChange |= 1 << workspace;
} else
fTemporaryDisplayModeChange &= ~(1 << workspace);
}
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_PROPOSE_MODE:
{
STRACE(("ServerApp %s: AS_PROPOSE_MODE\n", Signature()));
int32 id;
link.Read<int32>(&id);
display_mode target, low, high;
link.Read<display_mode>(&target);
link.Read<display_mode>(&low);
link.Read<display_mode>(&high);
status_t status = fDesktop->HWInterface()->ProposeMode(&target,
&low, &high);
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:
{
int32 id;
link.Read<int32>(&id);
display_mode* modeList;
uint32 count;
status_t status = fDesktop->HWInterface()->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(status);
fLink.Flush();
break;
}
case AS_GET_SCREEN_FRAME:
{
STRACE(("ServerApp %s: AS_GET_SCREEN_FRAME\n", Signature()));
int32 id;
link.Read<int32>(&id);
uint32 workspace;
link.Read<uint32>(&workspace);
BRect frame;
status_t status = fDesktop->GetScreenFrame(workspace, id, frame);
fLink.StartMessage(status);
if (status == B_OK)
fLink.Attach<BRect>(frame);
fLink.Flush();
break;
}
case AS_GET_DESKTOP_COLOR:
{
STRACE(("ServerApp %s: get desktop color\n", Signature()));
uint32 index;
link.Read<uint32>(&index);
fLink.StartMessage(B_OK);
fDesktop->LockSingleWindow();
if (index >= (uint32)kMaxWorkspaces)
index = fDesktop->CurrentWorkspace();
Workspace workspace(*fDesktop, index, true);
fLink.Attach<rgb_color>(workspace.Color());
fDesktop->UnlockSingleWindow();
fLink.Flush();
break;
}
case AS_SET_DESKTOP_COLOR:
{
STRACE(("ServerApp %s: set desktop color\n", Signature()));
rgb_color color;
uint32 index;
bool makeDefault;
link.Read<rgb_color>(&color);
link.Read<uint32>(&index);
if (link.Read<bool>(&makeDefault) != B_OK)
break;
fDesktop->LockAllWindows();
if (index >= (uint32)kMaxWorkspaces)
index = fDesktop->CurrentWorkspace();
Workspace workspace(*fDesktop, index);
workspace.SetColor(color, makeDefault);
fDesktop->UnlockAllWindows();
break;
}
case AS_GET_ACCELERANT_INFO:
{
STRACE(("ServerApp %s: get accelerant info\n", Signature()));
int32 id;
link.Read<int32>(&id);
accelerant_device_info accelerantInfo;
status_t status
= fDesktop->HWInterface()->GetDeviceInfo(&accelerantInfo);
if (status == B_OK) {
fLink.StartMessage(B_OK);
fLink.Attach<accelerant_device_info>(accelerantInfo);
} else
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_GET_MONITOR_INFO:
{
STRACE(("ServerApp %s: get monitor info\n", Signature()));
int32 id;
link.Read<int32>(&id);
monitor_info info;
status_t status = fDesktop->HWInterface()->GetMonitorInfo(&info);
if (status == B_OK) {
fLink.StartMessage(B_OK);
fLink.Attach<monitor_info>(info);
} else
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_GET_FRAME_BUFFER_CONFIG:
{
STRACE(("ServerApp %s: get frame buffer config\n", Signature()));
int32 id;
link.Read<int32>(&id);
frame_buffer_config config;
status_t status = fDesktop->HWInterface()->GetFrameBufferConfig(config);
if (status == B_OK) {
fLink.StartMessage(B_OK);
fLink.Attach<frame_buffer_config>(config);
} else
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_GET_RETRACE_SEMAPHORE:
{
STRACE(("ServerApp %s: get retrace semaphore\n", Signature()));
int32 id;
link.Read<int32>(&id);
fLink.StartMessage(B_OK);
fLink.Attach<sem_id>(fDesktop->HWInterface()->RetraceSemaphore());
fLink.Flush();
break;
}
case AS_GET_TIMING_CONSTRAINTS:
{
STRACE(("ServerApp %s: get timing constraints\n", Signature()));
int32 id;
link.Read<int32>(&id);
display_timing_constraints constraints;
status_t status = fDesktop->HWInterface()->GetTimingConstraints(
&constraints);
if (status == B_OK) {
fLink.StartMessage(B_OK);
fLink.Attach<display_timing_constraints>(constraints);
} else
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_GET_PIXEL_CLOCK_LIMITS:
{
STRACE(("ServerApp %s: get pixel clock limits\n", Signature()));
int32 id;
link.Read<int32>(&id);
display_mode mode;
link.Read<display_mode>(&mode);
uint32 low, high;
status_t status = fDesktop->HWInterface()->GetPixelClockLimits(&mode,
&low, &high);
if (status == B_OK) {
fLink.StartMessage(B_OK);
fLink.Attach<uint32>(low);
fLink.Attach<uint32>(high);
} else
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_SET_DPMS:
{
STRACE(("ServerApp %s: AS_SET_DPMS\n", Signature()));
int32 id;
link.Read<int32>(&id);
uint32 mode;
link.Read<uint32>(&mode);
status_t status = fDesktop->HWInterface()->SetDPMSMode(mode);
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_GET_DPMS_STATE:
{
STRACE(("ServerApp %s: AS_GET_DPMS_STATE\n", Signature()));
int32 id;
link.Read<int32>(&id);
uint32 state = fDesktop->HWInterface()->DPMSMode();
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()));
int32 id;
link.Read<int32>(&id);
uint32 capabilities = fDesktop->HWInterface()->DPMSCapabilities();
fLink.StartMessage(B_OK);
fLink.Attach<uint32>(capabilities);
fLink.Flush();
break;
}
case AS_SCREEN_SET_BRIGHTNESS:
{
STRACE(("ServerApp %s: AS_SCREEN_SET_BRIGHTNESS\n", Signature()));
int32 id;
link.Read<int32>(&id);
float brightness;
link.Read<float>(&brightness);
status_t status = fDesktop->SetBrightness(id, brightness);
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_SCREEN_GET_BRIGHTNESS:
{
STRACE(("ServerApp %s: AS_SCREEN_GET_BRIGHTNESS\n", Signature()));
int32 id;
link.Read<int32>(&id);
float brightness;
status_t result = fDesktop->HWInterface()->GetBrightness(&brightness);
fLink.StartMessage(result);
if (result == B_OK)
fLink.Attach<float>(brightness);
fLink.Flush();
break;
}
case AS_READ_BITMAP:
{
STRACE(("ServerApp %s: AS_READ_BITMAP\n", Signature()));
int32 id;
int32 token;
link.Read<int32>(&id);
link.Read<int32>(&token);
bool drawCursor = true;
link.Read<bool>(&drawCursor);
BRect bounds;
link.Read<BRect>(&bounds);
bool success = false;
BReference<ServerBitmap> bitmap(GetBitmap(token), true);
if (bitmap != NULL) {
if (fDesktop->GetDrawingEngine()->LockExclusiveAccess()) {
success = fDesktop->GetDrawingEngine()->ReadBitmap(bitmap,
drawCursor, bounds) == B_OK;
fDesktop->GetDrawingEngine()->UnlockExclusiveAccess();
}
}
if (success)
fLink.StartMessage(B_OK);
else
fLink.StartMessage(B_BAD_VALUE);
fLink.Flush();
break;
}
case AS_GET_ACCELERANT_PATH:
{
int32 id;
fLink.Read<int32>(&id);
BString path;
status_t status = fDesktop->HWInterface()->GetAccelerantPath(path);
fLink.StartMessage(status);
if (status == B_OK)
fLink.AttachString(path.String());
fLink.Flush();
break;
}
case AS_GET_DRIVER_PATH:
{
int32 id;
fLink.Read<int32>(&id);
BString path;
status_t status = fDesktop->HWInterface()->GetDriverPath(path);
fLink.StartMessage(status);
if (status == B_OK)
fLink.AttachString(path.String());
fLink.Flush();
break;
}
case AS_DIRECT_SCREEN_LOCK:
{
bool lock;
link.Read<bool>(&lock);
status_t status;
if (lock)
status = fDesktop->LockDirectScreen(ClientTeam());
else
status = fDesktop->UnlockDirectScreen(ClientTeam());
fLink.StartMessage(status);
fLink.Flush();
break;
}
case AS_SET_SUBPIXEL_ANTIALIASING:
{
bool subpix;
if (link.Read<bool>(&subpix) == B_OK) {
LockedDesktopSettings settings(fDesktop);
settings.SetSubpixelAntialiasing(subpix);
}
fDesktop->Redraw();
break;
}
case AS_GET_SUBPIXEL_ANTIALIASING:
{
DesktopSettings settings(fDesktop);
fLink.StartMessage(B_OK);
fLink.Attach<bool>(settings.SubpixelAntialiasing());
fLink.Flush();
break;
}
case AS_SET_HINTING:
{
uint8 hinting;
if (link.Read<uint8>(&hinting) == B_OK && hinting < 3) {
LockedDesktopSettings settings(fDesktop);
if (hinting != settings.Hinting()) {
settings.SetHinting(hinting);
fDesktop->Redraw();
}
}
break;
}
case AS_GET_HINTING:
{
DesktopSettings settings(fDesktop);
fLink.StartMessage(B_OK);
fLink.Attach<uint8>(settings.Hinting());
fLink.Flush();
break;
}
case AS_SET_SUBPIXEL_AVERAGE_WEIGHT:
{
uint8 averageWeight;
if (link.Read<uint8>(&averageWeight) == B_OK) {
LockedDesktopSettings settings(fDesktop);
settings.SetSubpixelAverageWeight(averageWeight);
}
fDesktop->Redraw();
break;
}
case AS_GET_SUBPIXEL_AVERAGE_WEIGHT:
{
DesktopSettings settings(fDesktop);
fLink.StartMessage(B_OK);
fLink.Attach<uint8>(settings.SubpixelAverageWeight());
fLink.Flush();
break;
}
case AS_SET_SUBPIXEL_ORDERING:
{
bool subpixelOrdering;
if (link.Read<bool>(&subpixelOrdering) == B_OK) {
LockedDesktopSettings settings(fDesktop);
settings.SetSubpixelOrderingRegular(subpixelOrdering);
}
fDesktop->Redraw();
break;
}
case AS_GET_SUBPIXEL_ORDERING:
{
DesktopSettings settings(fDesktop);
fLink.StartMessage(B_OK);
fLink.Attach<bool>(settings.IsSubpixelOrderingRegular());
fLink.Flush();
break;
}
default:
printf("ServerApp %s received unhandled message code %" B_PRId32
"\n", Signature(), code);
if (link.NeedsReply()) {
fLink.StartMessage(B_ERROR);
fLink.Flush();
} else
puts("message doesn't need a reply!");
break;
}
}
*/
void
ServerApp::_MessageLooper()
{
thread_info threadInfo;
get_thread_info(fThread, &threadInfo);
fLink.StartMessage(B_OK);
fLink.Attach<port_id>(fMessagePort);
fLink.Attach<area_id>(fDesktop->SharedReadOnlyArea());
fLink.Attach<team_id>(threadInfo.team);
fLink.Flush();
BPrivate::LinkReceiver &receiver = fLink.Receiver();
int32 code;
status_t err = B_OK;
while (!fQuitting) {
STRACE(("info: ServerApp::_MessageLooper() listening on port %" B_PRId32
".\n", fMessagePort));
err = receiver.GetNextMessage(code);
if (err != B_OK || code == B_QUIT_REQUESTED) {
STRACE(("ServerApp: application seems to be gone...\n"));
BPrivate::LinkSender link(fDesktop->MessagePort());
link.StartMessage(AS_DELETE_APP);
link.Attach<thread_id>(Thread());
link.Flush();
break;
}
switch (code) {
case kMsgAppQuit:
fQuitting = true;
break;
case AS_QUIT_APP:
{
STRACE(("ServerApp %s:Server shutdown notification received\n",
Signature()));
#if TEST_MODE
BMessage pleaseQuit(B_QUIT_REQUESTED);
SendMessageToClient(&pleaseQuit);
#endif
break;
}
default:
STRACE(("ServerApp %s: Got a Message to dispatch\n",
Signature()));
_DispatchMessage(code, receiver);
break;
}
}
thread_id sender;
sem_id shutdownSemaphore;
receive_data(&sender, &shutdownSemaphore, sizeof(sem_id));
delete this;
if (shutdownSemaphore >= B_OK)
release_sem(shutdownSemaphore);
}
status_t
ServerApp::_CreateWindow(int32 code, BPrivate::LinkReceiver& link,
port_id& clientReplyPort)
{
BRect frame;
int32 bitmapToken;
uint32 look;
uint32 feel;
uint32 flags;
uint32 workspaces;
int32 token;
port_id looperPort;
char* title;
if (code == AS_CREATE_OFFSCREEN_WINDOW)
link.Read<int32>(&bitmapToken);
link.Read<BRect>(&frame);
link.Read<uint32>(&look);
link.Read<uint32>(&feel);
link.Read<uint32>(&flags);
link.Read<uint32>(&workspaces);
link.Read<int32>(&token);
link.Read<port_id>(&clientReplyPort);
link.Read<port_id>(&looperPort);
if (link.ReadString(&title) != B_OK)
return B_ERROR;
if (!frame.IsValid()) {
frame.right = frame.left + 1;
frame.bottom = frame.top + 1;
}
status_t status = B_NO_MEMORY;
ServerWindow *window = NULL;
if (code == AS_CREATE_OFFSCREEN_WINDOW) {
ServerBitmap* bitmap = GetBitmap(bitmapToken);
if (bitmap != NULL) {
window = new (nothrow) OffscreenServerWindow(title, this,
clientReplyPort, looperPort, token, bitmap);
} else
status = B_ERROR;
} else {
window = new (nothrow) ServerWindow(title, this, clientReplyPort,
looperPort, token);
STRACE(("\nServerApp %s: New Window %s (%g:%g, %g:%g)\n",
Signature(), title, frame.left, frame.top,
frame.right, frame.bottom));
}
free(title);
if (window != NULL) {
status = window->Init(frame, (window_look)look, (window_feel)feel,
flags, workspaces);
if (status == B_OK) {
status = window->Run();
if (status != B_OK) {
syslog(LOG_ERR, "ServerApp::_CreateWindow() - failed to run "
"the window thread\n");
}
}
if (status != B_OK)
delete window;
}
return status;
}
bool
ServerApp::_HasWindowUnderMouse()
{
BAutolock locker(fWindowListLock);
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
ServerWindow* serverWindow = fWindowList.ItemAt(i);
if (fDesktop->ViewUnderMouse(serverWindow->Window()) != B_NULL_TOKEN)
return true;
}
return false;
}
bool
ServerApp::_AddBitmap(ServerBitmap* bitmap)
{
BAutolock _(fMapLocker);
try {
fBitmapMap.insert(std::make_pair(bitmap->Token(), BReference<ServerBitmap>(bitmap, false)));
} catch (std::bad_alloc& exception) {
return false;
}
bitmap->SetOwner(this);
return true;
}
void
ServerApp::_DeleteBitmap(ServerBitmap* bitmap)
{
ASSERT(fMapLocker.IsLocked());
gBitmapManager->BitmapRemoved(bitmap);
fBitmapMap.erase(bitmap->Token());
}
ServerBitmap*
ServerApp::_FindBitmap(int32 token) const
{
ASSERT(fMapLocker.IsLocked());
BitmapMap::const_iterator iterator = fBitmapMap.find(token);
if (iterator == fBitmapMap.end())
return NULL;
return iterator->second;
}
ServerPicture*
ServerApp::_FindPicture(int32 token) const
{
ASSERT(fMapLocker.IsLocked());
PictureMap::const_iterator iterator = fPictureMap.find(token);
if (iterator == fPictureMap.end())
return NULL;
return iterator->second;
}