Added prototyp #7 and test application to tree.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1862 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
DarkWyrm 2002-11-06 22:50:38 +00:00
parent a3d39a9e8a
commit 54b288ebda
66 changed files with 14678 additions and 1 deletions

View File

@ -1,4 +1,4 @@
SubDir OBOS_TOP src servers app ;
SubInclude OBOS_TOP src servers app proto6 ;
SubInclude OBOS_TOP src servers app proto7 ;

View File

@ -0,0 +1,658 @@
/*
AppServer.cpp
File for the main app_server thread. This particular thread monitors for
application start and quit messages. It also starts the housekeeping threads
and initializes most of the server's globals.
*/
#include <Message.h>
#include <AppDefs.h>
#include "scheduler.h"
#include <iostream.h>
#include <stdio.h>
#include <OS.h>
#include <Debug.h>
#include "AppServer.h"
#include "FontServer.h"
#include "Layer.h"
#include "ServerApp.h"
#include "ServerWindow.h"
#include "Desktop.h"
#include "ServerProtocol.h"
#include "PortLink.h"
#include "DisplayDriver.h"
#include "DebugTools.h"
#include "BeDecorator.h"
//#define DEBUG_APPSERVER_THREAD
//#define DEBUG_POLLER_THREAD
// This bad boy holds only the top layer for each workspace
//BList *layerlist;
// Used for mediating access to the layer lists
//BLocker *layerlock;
// Used for access via instantiate_decorator
AppServer *app_server;
AppServer::AppServer(void) : BApplication("application/x-vnd.obe-OBAppServer")
{
#ifdef DEBUG_APPSERVER_THREAD
printf("AppServer()\n");
#endif
mouseport=create_port(30,SERVER_INPUT_PORT);
messageport=create_port(20,SERVER_PORT_NAME);
#ifdef DEBUG_APPSERVER_THREAD
printf("Server message port: %ld\n",messageport);
printf("Server input port: %ld\n",mouseport);
#endif
applist=new BList(0);
quitting_server=false;
exit_poller=false;
fontserver=new FontServer;
fontserver->Lock();
fontserver->ScanDirectory("/boot/beos/etc/fonts/ttfonts/");
// fontserver->ScanDirectory("/boot/beos/etc/fonts/PS-Type1/");
// fontserver->ScanDirectory("/boot/home/config/fonts/ttfonts/");
// fontserver->ScanDirectory("/boot/home/config/fonts/psfonts/");
fontserver->SaveList();
if(!fontserver->SetSystemPlain("Dutch801 Rm BT","Roman",12))
printf("Couldn't set plain to Dutch801 Rm BT, Roman 12 pt\n");
if(!fontserver->SetSystemBold("Dutch801 Rm BT","Bold",12))
printf("Couldn't set bold to Dutch801 Rm BT, Bold 12 pt\n");
if(!fontserver->SetSystemFixed("Courier10 BT","Roman",12))
printf("Couldn't set fixed to Courier10 BT, Roman 12 pt\n");
fontserver->Unlock();
// Set up the Desktop
init_desktop(3);
// This is necessary to mediate access between the Poller and app_server threads
active_lock=new BLocker;
// This locker is for app_server and Picasso to vy for control of the ServerApp list
applist_lock=new BLocker;
// This locker is to mediate access to the make_decorator pointer
decor_lock=new BLocker;
// Get the driver first - Poller thread utilizes the thing
driver=get_gfxdriver();
// Spawn our input-polling thread
poller_id = spawn_thread(PollerThread, "Poller", B_NORMAL_PRIORITY, this);
if (poller_id >= 0)
resume_thread(poller_id);
// Spawn our thread-monitoring thread
picasso_id = spawn_thread(PicassoThread,"Picasso", B_NORMAL_PRIORITY, this);
if (picasso_id >= 0)
resume_thread(picasso_id);
active_app=-1;
p_active_app=NULL;
make_decorator=NULL;
// layerlock=new BLocker;
// layerlist=new BList(1);
LoadGUIColors();
}
AppServer::~AppServer(void)
{
shutdown_desktop();
ServerApp *tempapp;
// Layer *templayer;
int32 i;
applist_lock->Lock();
for(i=0;i<applist->CountItems();i++)
{
tempapp=(ServerApp *)applist->ItemAt(i);
if(tempapp!=NULL)
delete tempapp;
}
delete applist;
applist_lock->Unlock();
/* layerlock->Lock();
for(i=0;i<layerlist->CountItems();i++)
{
templayer=(Layer *)layerlist->ItemAt(i);
if(templayer!=NULL)
{
templayer->PruneTree();
delete templayer;
}
}
delete layerlist;
layerlock->Unlock();
delete layerlock;
*/ delete active_lock;
delete applist_lock;
// If these threads are still running, kill them - after this, if exit_poller
// is deleted, who knows what will happen... These things will just return an
// error and fail if the threads have already exited.
kill_thread(poller_id);
kill_thread(picasso_id);
delete decor_lock;
delete fontserver;
make_decorator=NULL;
}
thread_id AppServer::Run(void)
{
#ifdef DEBUG_APPSERVER_THREAD
printf("AppServer::Run()\n");
#endif
MainLoop();
return 0;
}
void AppServer::MainLoop(void)
{
// Main loop (duh). Monitors the message queue and dispatches as appropriate.
// Input messages are handled by the poller, however.
#ifdef DEBUG_APPSERVER_THREAD
printf("AppServer::MainLoop()\n");
#endif
int32 msgcode;
int8 *msgbuffer=NULL;
ssize_t buffersize,bytesread;
for(;;)
{
buffersize=port_buffer_size(messageport);
if(buffersize>0)
msgbuffer=new int8[buffersize];
bytesread=read_port(messageport,&msgcode,msgbuffer,buffersize);
if (bytesread != B_BAD_PORT_ID && bytesread != B_TIMED_OUT && bytesread != B_WOULD_BLOCK)
{
switch(msgcode)
{
case CREATE_APP:
case DELETE_APP:
case GET_SCREEN_MODE:
case B_QUIT_REQUESTED:
case UPDATED_CLIENT_FONTLIST:
case QUERY_FONTS_CHANGED:
DispatchMessage(msgcode,msgbuffer);
break;
default:
{
#ifdef DEBUG_APPSERVER_THREAD
printf("Server received unexpected code %ld\n",msgcode);
#endif
break;
}
}
}
if(buffersize>0)
delete msgbuffer;
if(msgcode==DELETE_APP || msgcode==B_QUIT_REQUESTED)
{
if(quitting_server==true && applist->CountItems()==0)
break;
}
}
// Make sure our polling thread has exited
if(find_thread("Poller")!=B_NAME_NOT_FOUND)
kill_thread(poller_id);
}
void AppServer::DispatchMessage(int32 code, int8 *buffer)
{
int8 *index=buffer;
switch(code)
{
case CREATE_APP:
{
// Create the ServerApp to node monitor a new BApplication
#ifdef DEBUG_APPSERVER_THREAD
printf("AppServer: Create App\n");
#endif
// Attached data:
// 1) port_id - port to reply to
// 2) port_id - receiver port of a regular app
// 3) char * - signature of the regular app
// Find the necessary data
port_id reply_port=*((port_id*)index); index+=sizeof(port_id);
port_id app_port=*((port_id*)index); index+=sizeof(port_id);
char *app_signature=(char *)index;
// Create the ServerApp subthread for this app
applist_lock->Lock();
ServerApp *newapp=new ServerApp(app_port,app_signature);
applist->AddItem(newapp);
applist_lock->Unlock();
active_lock->Lock();
p_active_app=newapp;
active_app=applist->CountItems()-1;
PortLink *replylink=new PortLink(reply_port);
replylink->SetOpCode(SET_SERVER_PORT);
replylink->Attach((int32)newapp->receiver);
replylink->Flush();
delete replylink;
active_lock->Unlock();
newapp->Run();
break;
}
case DELETE_APP:
{
// Delete a ServerApp. Received only from the respective ServerApp when a
// BApplication asks it to quit.
#ifdef DEBUG_APPSERVER_THREAD
printf("AppServer: Delete App\n");
#endif
// Attached Data:
// 1) thread_id - thread ID of the ServerApp to be deleted
int32 i, appnum=applist->CountItems();
ServerApp *srvapp;
thread_id srvapp_id=*((thread_id*)buffer);
// Run through the list of apps and nuke the proper one
for(i=0;i<appnum;i++)
{
srvapp=(ServerApp *)applist->ItemAt(i);
if(srvapp!=NULL && srvapp->monitor_thread==srvapp_id)
{
applist_lock->Lock();
srvapp=(ServerApp *)applist->RemoveItem(i);
if(srvapp)
{
delete srvapp;
srvapp=NULL;
}
applist_lock->Unlock();
active_lock->Lock();
if(applist->CountItems()==0)
{
// active==-1 signifies that no other apps are running - NOT good
active_app=-1;
}
else
{
// we actually still have apps running, so make a new one active
if(active_app>0)
active_app--;
else
active_app=0;
}
p_active_app=(active_app>-1)?(ServerApp*)applist->ItemAt(active_app):NULL;
active_lock->Unlock();
break; // jump out of our for() loop
}
}
break;
}
case UPDATED_CLIENT_FONTLIST:
{
// received when the client-side global font list has been
// refreshed
fontserver->Lock();
fontserver->FontsUpdated();
fontserver->Unlock();
break;
}
case QUERY_FONTS_CHANGED:
{
// Client application is asking if the font list has changed since
// the last client-side refresh
// Attached data:
// 1) port_id reply port
fontserver->Lock();
bool needs_update=fontserver->FontsNeedUpdated();
fontserver->Unlock();
PortLink *pl=new PortLink(*((port_id*)index));
pl->SetOpCode( (needs_update)?SERVER_TRUE:SERVER_FALSE );
pl->Flush();
delete pl;
break;
}
case GET_SCREEN_MODE:
{
// Synchronous message call to get the stats on the current screen mode
// in the app_server. Simply a hack in place for the Input Server until
// BScreens are done.
#ifdef DEBUG_APPSERVER_THREAD
printf("AppServer: Get Screen Mode\n");
#endif
// Attached Data:
// 1) port_id - port to reply to
// Returned Data:
// 1) int32 width
// 2) int32 height
// 3) int depth
PortLink *replylink=new PortLink(*((port_id*)index));
replylink->SetOpCode(GET_SCREEN_MODE);
replylink->Attach((int16)driver->GetWidth());
replylink->Attach((int16)driver->GetHeight());
replylink->Attach((int16)driver->GetDepth());
replylink->Flush();
delete replylink;
break;
}
case B_QUIT_REQUESTED:
{
#ifdef DEBUG_APPSERVER_THREAD
printf("Shutdown sequence initiated.\n");
#endif
// Attached Data:
// none
// We've been asked to quit, so (for now) broadcast to all
// test apps to quit. This situation will occur only when the server
// is compiled as a regular Be application.
PortLink *applink=new PortLink(0);
ServerApp *srvapp;
applist_lock->Lock();
int32 i,appnum=applist->CountItems();
applink->SetOpCode(QUIT_APP);
for(i=0;i<appnum;i++)
{
srvapp=(ServerApp *)applist->ItemAt(i);
if(srvapp!=NULL)
{
applink->SetPort(srvapp->receiver);
applink->Flush();
}
}
applist_lock->Unlock();
delete applink;
// So when we delete the last ServerApp, we can exit the server
quitting_server=true;
exit_poller=true;
break;
}
default:
//printf("Unexpected message %ld (%lx) in AppServer::DispatchMessage()\n",code,code);
break;
}
}
bool AppServer::LoadDecorator(BString path)
{
// Loads a window decorator based on the supplied path and forces a decorator update.
// If it cannot load the specified decorator, it will retain the current one and
// return false.
create_decorator *pcreatefunc=NULL;
get_version *pversionfunc=NULL;
status_t stat;
image_id addon;
addon=load_add_on(path.String());
stat=get_image_symbol(addon, "get_decorator_version", B_SYMBOL_TYPE_TEXT, (void**)&pversionfunc);
if(stat!=B_OK)
{
printf("ERROR: Could not get version for Decorator %s\n", path.String());
unload_add_on(addon);
return false;
}
// As of now, we do nothing with decorator versions, but the possibility exists
// that the API will change even though I cannot forsee any reason to do so. If
// we *did* do anything with decorator versions, the assignment to a global would
// go here.
stat=get_image_symbol(addon, "instantiate_decorator", B_SYMBOL_TYPE_TEXT, (void**)&pversionfunc);
if(stat!=B_OK)
{
printf("ERROR: Could not get allocator for Decorator %s\n", path.String());
unload_add_on(addon);
return false;
}
decor_lock->Lock();
make_decorator=pcreatefunc;
decorator_id=addon;
decor_lock->Unlock();
return true;
}
void AppServer::LoadDefaultDecorator(void)
{
// This function is called on server startup to provide a fallback decorator in
// case the decorator specified in the config file cannot be loaded. It just
// wouldn't do to have windows with no borders. ;) It also unloads any loaded
// decorator addons. We can specify that we want the default. It is no less
// functional - just internal.
}
Decorator *instantiate_decorator(BRect rect, int32 wlook, int32 wfeel, int32 wflags)
{
Decorator *decor=NULL;
app_server->LockDecorator();
if(app_server->make_decorator!=NULL)
decor=app_server->make_decorator(rect,wlook,wfeel,wflags);
else
{
decor=new BeDecorator(rect,wlook,wfeel,wflags);
// decor=new WinDecorator(lay, dflags, wlook);
// decor=new YMakDecorator(lay, dflags, wlook);
}
decor->SetDriver(get_gfxdriver());
app_server->UnlockDecorator();
return decor;
}
void AppServer::Poller(void)
{
// This thread handles nothing but input messages for mouse and keyboard
int32 msgcode;
int8 *msgbuffer=NULL,*index;
ssize_t buffersize,bytesread;
for(;;)
{
buffersize=port_buffer_size(mouseport);
if(buffersize>0)
msgbuffer=new int8[buffersize];
bytesread=read_port(mouseport,&msgcode,msgbuffer,buffersize);
if (bytesread != B_BAD_PORT_ID && bytesread != B_TIMED_OUT && bytesread != B_WOULD_BLOCK)
{
switch(msgcode)
{
// We don't need to do anything with these two, so just pass them
// onto the active application. Eventually, we will pass them onto
// the window which is currently under the cursor.
case B_MOUSE_DOWN:
if(!msgbuffer)
{
#ifdef DEBUG_POLLER_THREAD
printf("Poller: MouseDown() - Empty buffer\n");
#endif
break;
}
case B_MOUSE_UP:
{
if(!msgbuffer)
{
#ifdef DEBUG_POLLER_THREAD
printf("Poller: MouseUp() - Empty buffer\n");
#endif
break;
}
/*
active_lock->Lock();
if(active_app>-1 && p_active_app!=NULL)
write_port(p_active_app->receiver, msgcode,msgbuffer,buffersize);
active_lock->Unlock();
*/
#ifdef DEBUG_POLLER_THREAD
printf("Poller: MouseDown/MouseUp\n");
#endif
ServerWindow::HandleMouseEvent(msgcode,msgbuffer);
break;
}
// Process the cursor and then pass it on
case B_MOUSE_MOVED:
{
// Attached data:
// 1) int64 - time of mouse click
// 2) float - x coordinate of mouse click
// 3) float - y coordinate of mouse click
// 4) int32 - buttons down
index=msgbuffer;
if(!index)
{
#ifdef DEBUG_POLLER_THREAD
printf("Poller: MouseMoved() - Empty buffer\n");
#endif
break;
}
// Time sent is not necessary for cursor processing.
index += sizeof(int64);
float tempx=0,tempy=0;
tempx=*((float*)index);
index+=sizeof(float);
tempy=*((float*)index);
index+=sizeof(float);
#ifdef DEBUG_POLLER_THREAD
printf("Poller: MouseMoved(%f,%f)\n",tempx,tempy);
#endif
driver->MoveCursorTo(tempx,tempy);
/* active_lock->Lock();
if(active_app>-1 && p_active_app!=NULL)
write_port(p_active_app->receiver, msgcode,msgbuffer,buffersize);
active_lock->Unlock();
*/
ServerWindow::HandleMouseEvent(msgcode,msgbuffer);
break;
}
default:
//printf("Server::Poller received unexpected code %ld\n",msgcode);
break;
}
}
if(buffersize>0)
delete msgbuffer;
if(exit_poller)
break;
}
}
int32 AppServer::PollerThread(void *data)
{
#ifdef DEBUG_POLLER_THREAD
printf("Starting Poller thread...\n");
#endif
AppServer *server=(AppServer *)data;
// This won't return until it's told to
server->Poller();
#ifdef DEBUG_POLLER_THREAD
printf("Exiting Poller thread...\n");
#endif
exit_thread(B_OK);
return B_OK;
}
void AppServer::Picasso(void)
{
int32 i;
ServerApp *app;
for(;;)
{
applist_lock->Lock();
for(i=0;i<applist->CountItems(); i++)
{
app=(ServerApp*)applist->ItemAt(i);
ASSERT(app!=NULL);
app->PingTarget();
}
applist_lock->Unlock();
// if poller thread has to exit, so do we - I just was too lazy
// to rename the variable name. ;)
if(exit_poller)
break;
// we do this every other second so as not to suck *too* many CPU cycles
snooze(2000000);
}
}
int32 AppServer::PicassoThread(void *data)
{
#ifdef DEBUG_APPSERVER_THREAD
printf("Starting Picasso thread...\n");
#endif
AppServer *server=(AppServer *)data;
// This won't return until it's told to
server->Picasso();
#ifdef DEBUG_APPSERVER_THREAD
printf("Exiting Picasso thread...\n");
#endif
exit_thread(B_OK);
return B_OK;
}
int main( int argc, char** argv )
{
// There can be only one....
if(find_port(SERVER_PORT_NAME)!=B_NAME_NOT_FOUND)
return -1;
app_server = new AppServer();
app_server->Run();
delete app_server;
return 0;
}

View File

@ -0,0 +1,51 @@
#ifndef _OPENBEOS_APP_SERVER_H_
#define _OPENBEOS_APP_SERVER_H_
#include <OS.h>
#include <Locker.h>
#include <Application.h>
#include <List.h>
//#include <Window.h> // for window_look
#include "Decorator.h"
class Layer;
class BMessage;
class ServerApp;
class DisplayDriver;
class AppServer : public BApplication
{
public:
AppServer(void);
~AppServer(void);
thread_id Run(void);
void MainLoop(void);
port_id messageport,mouseport;
void Poller(void);
void Picasso(void);
void LockDecorator(void) { if(decor_lock) decor_lock->Lock(); }
void UnlockDecorator(void) { if(decor_lock) decor_lock->Unlock(); }
create_decorator *make_decorator; // global function pointer
private:
friend Decorator *instantiate_decorator(Layer *lay, uint32 dflags, uint32 wlook);
void DispatchMessage(int32 code, int8 *buffer);
static int32 PollerThread(void *data);
static int32 PicassoThread(void *data);
bool LoadDecorator(BString path);
void LoadDefaultDecorator(void);
image_id decorator_id;
bool quitting_server;
BList *applist;
int32 active_app;
ServerApp *p_active_app;
thread_id poller_id, picasso_id;
BLocker *active_lock, *applist_lock, *decor_lock;
bool exit_poller;
DisplayDriver *driver;
};
Decorator *instantiate_decorator(BRect rect, int32 wlook, int32 wfeel, int32 wflags);
#endif

View File

@ -0,0 +1,499 @@
#include "DisplayDriver.h"
#include <View.h>
#include "LayerData.h"
#include "ColorUtils.h"
#include "BeDecorator.h"
#include "RGBColor.h"
#include "Desktop.h"
//#define DEBUG_DECOR
#ifdef DEBUG_DECOR
#include <stdio.h>
#endif
BeDecorator::BeDecorator(BRect rect, int32 wlook, int32 wfeel, int32 wflags)
: Decorator(rect,wlook,wfeel,wflags)
{
#ifdef DEBUG_DECOR
printf("BeDecorator()\n");
#endif
taboffset=0;
// These hard-coded assignments will go bye-bye when the system colors
// API is implemented
// commented these out because they are taken care of by the SetFocus() call
*colors=GetGUIColors();
SetFocus(false);
frame_highercol.SetColor(216,216,216);
frame_lowercol.SetColor(110,110,110);
textcol.SetColor(0,0,0);
frame_highcol=frame_lowercol.MakeBlendColor(frame_highercol,0.75);
frame_midcol=frame_lowercol.MakeBlendColor(frame_highercol,0.5);
frame_lowcol=frame_lowercol.MakeBlendColor(frame_highercol,0.25);
_DoLayout();
// This flag is used to determine whether or not we're moving the tab
slidetab=false;
solidhigh=0xFFFFFFFFFFFFFFFFLL;
solidlow=0;
tab_highcol=colors->window_tab;
tab_lowcol=colors->window_tab;
}
BeDecorator::~BeDecorator(void)
{
#ifdef DEBUG_DECOR
printf("~BeDecorator()\n");
#endif
}
click_type BeDecorator::Clicked(BPoint pt, int32 buttons, int32 modifiers)
{
if(closerect.Contains(pt))
{
#ifdef DEBUG_DECOR
printf("BeDecorator():Clicked() - Close\n");
#endif
return CLICK_CLOSE;
}
if(zoomrect.Contains(pt))
{
#ifdef DEBUG_DECOR
printf("BeDecorator():Clicked() - Zoom\n");
#endif
return CLICK_ZOOM;
}
if(resizerect.Contains(pt) && look==WLOOK_DOCUMENT)
{
#ifdef DEBUG_DECOR
printf("BeDecorator():Clicked() - Resize thumb\n");
#endif
return CLICK_RESIZE;
}
// Clicking in the tab?
if(tabrect.Contains(pt))
{
// Here's part of our window management stuff
if(buttons==B_PRIMARY_MOUSE_BUTTON && !GetFocus())
return CLICK_MOVETOFRONT;
if(buttons==B_SECONDARY_MOUSE_BUTTON)
return CLICK_MOVETOBACK;
return CLICK_DRAG;
}
// We got this far, so user is clicking on the border?
BRect brect(frame);
brect.top+=19;
BRect clientrect(brect.InsetByCopy(3,3));
if(brect.Contains(pt) && !clientrect.Contains(pt))
{
#ifdef DEBUG_DECOR
printf("BeDecorator():Clicked() - Drag\n");
#endif
if(resizerect.Contains(pt))
return CLICK_RESIZE;
return CLICK_DRAG;
}
// Guess user didn't click anything
#ifdef DEBUG_DECOR
printf("BeDecorator():Clicked()\n");
#endif
return CLICK_NONE;
}
void BeDecorator::_DoLayout(void)
{
// Here we determine the size of every rectangle that we use
// internally when we are given the size of the client rectangle.
// Current version simply makes everything fit inside the rect
// instead of building around it. This will change.
#ifdef DEBUG_DECOR
printf("BeDecorator()::_DoLayout()"); rect.PrintToStream();
#endif
tabrect=frame;
resizerect=frame;
borderrect=frame;
closerect=frame;
closerect.left+=(look==WLOOK_FLOATING)?2:4;
closerect.top+=(look==WLOOK_FLOATING)?6:4;
closerect.right=closerect.left+10;
closerect.bottom=closerect.top+10;
borderrect.top+=19;
resizerect.top=resizerect.bottom-18;
resizerect.left=resizerect.right-18;
tabrect.bottom=tabrect.top+18;
/* if(GetTitle())
{
float titlewidth=closerect.right
+driver->StringWidth(layer->name->String(),
layer->name->Length())
+35;
tabrect.right=(titlewidth<frame.right -1)?titlewidth:frame.right;
}
else
*/ tabrect.right=tabrect.left+tabrect.Width()/2;
if(look==WLOOK_FLOATING)
tabrect.top+=4;
zoomrect=tabrect;
zoomrect.top+=(look==WLOOK_FLOATING)?2:4;
zoomrect.right-=4;
zoomrect.bottom-=4;
zoomrect.left=zoomrect.right-10;
zoomrect.bottom=zoomrect.top+10;
textoffset=(look==WLOOK_FLOATING)?5:7;
}
void BeDecorator::MoveBy(float x, float y)
{
MoveBy(BPoint(x,y));
}
void BeDecorator::MoveBy(BPoint pt)
{
// Move all internal rectangles the appropriate amount
frame.OffsetBy(pt);
closerect.OffsetBy(pt);
tabrect.OffsetBy(pt);
resizerect.OffsetBy(pt);
borderrect.OffsetBy(pt);
zoomrect.OffsetBy(pt);
}
void BeDecorator::ResizeBy(float x, float y)
{
ResizeBy(BPoint(x,y));
}
void BeDecorator::ResizeBy(BPoint pt)
{
frame.right+=pt.x;
frame.bottom+=pt.y;
_DoLayout();
}
BRegion * BeDecorator::GetFootprint(void)
{
// This function calculates the decorator's footprint in coordinates
// relative to the layer. This is most often used to set a WindowBorder
// object's visible region.
BRegion *reg=new BRegion(borderrect);
reg->Include(tabrect);
return reg;
}
void BeDecorator::_DrawTitle(BRect r)
{
// Designed simply to redraw the title when it has changed on
// the client side.
/* driver->SetDrawingMode(B_OP_OVER);
rgb_color tmpcol=driver->HighColor();
driver->SetHighColor(textcol.red,textcol.green,textcol.blue);
driver->DrawString((char *)string,strlen(string),
BPoint(closerect.right+textoffset,closerect.bottom-1));
driver->SetHighColor(tmpcol.red,tmpcol.green,tmpcol.blue);
driver->SetDrawingMode(B_OP_COPY);
*/
}
void BeDecorator::_SetFocus(void)
{
// SetFocus() performs necessary duties for color swapping and
// other things when a window is deactivated or activated.
if(GetFocus())
{
// tab_highcol.SetColor(255,236,33);
// tab_lowcol.SetColor(234,181,0);
tab_highcol=colors->window_tab;
tab_lowcol=colors->window_tab;
button_highcol.SetColor(255,255,0);
button_lowcol.SetColor(255,203,0);
}
else
{
tab_highcol.SetColor(235,235,235);
tab_lowcol.SetColor(160,160,160);
button_highcol.SetColor(229,229,229);
button_lowcol.SetColor(153,153,153);
}
}
void BeDecorator::Draw(BRect update)
{
// We need to draw a few things: the tab, the resize thumb, the borders,
// and the buttons
_DrawTab(update);
// Draw the top view's client area - just a hack :)
RGBColor blue(100,100,255);
layerdata.highcolor=blue;
if(borderrect.Intersects(update))
driver->FillRect(borderrect,&layerdata,(int8*)&solidhigh);
_DrawFrame(update);
}
void BeDecorator::Draw(void)
{
// Easy way to draw everything - no worries about drawing only certain
// things
// Draw the top view's client area - just a hack :)
RGBColor blue(100,100,255);
layerdata.highcolor=blue;
driver->FillRect(borderrect,&layerdata,(int8*)&solidhigh);
DrawFrame();
DrawTab();
}
void BeDecorator::_DrawZoom(BRect r)
{
// If this has been implemented, then the decorator has a Zoom button
// which should be drawn based on the state of the member zoomstate
BRect zr=r;
zr.left+=zr.Width()/3;
zr.top+=zr.Height()/3;
DrawBlendedRect(zr,GetZoom());
DrawBlendedRect(zr.OffsetToCopy(r.LeftTop()),GetZoom());
}
void BeDecorator::_DrawClose(BRect r)
{
// Just like DrawZoom, but for a close button
DrawBlendedRect(r,GetClose());
}
void BeDecorator::_DrawTab(BRect r)
{
// If a window has a tab, this will draw it and any buttons which are
// in it.
if(look==WLOOK_NO_BORDER)
return;
layerdata.highcolor=frame_lowcol;
driver->StrokeRect(tabrect,&layerdata,(int8*)&solidhigh);
// UpdateTitle(layer->name->String());
layerdata.highcolor=colors->window_tab;
driver->FillRect(tabrect.InsetByCopy(1,1),&layerdata,(int8*)&solidhigh);
// Draw the buttons if we're supposed to
if(!(flags & NOT_CLOSABLE))
_DrawClose(closerect);
if(!(flags & NOT_ZOOMABLE))
_DrawZoom(zoomrect);
}
void BeDecorator::DrawBlendedRect(BRect r, bool down)
{
// This bad boy is used to draw a rectangle with a gradient.
// Note that it is not part of the Decorator API - it's specific
// to just the BeDecorator. Called by DrawZoom and DrawClose
// Actually just draws a blended square
int32 w=r.IntegerWidth(), h=r.IntegerHeight();
rgb_color tmpcol,halfcol, startcol, endcol;
float rstep,gstep,bstep,i;
int steps=(w<h)?w:h;
if(down)
{
startcol=button_lowcol.GetColor32();
endcol=button_highcol.GetColor32();
}
else
{
startcol=button_highcol.GetColor32();
endcol=button_lowcol.GetColor32();
}
halfcol=MakeBlendColor(startcol,endcol,0.5);
rstep=float(startcol.red-halfcol.red)/steps;
gstep=float(startcol.green-halfcol.green)/steps;
bstep=float(startcol.blue-halfcol.blue)/steps;
for(i=0;i<=steps; i++)
{
SetRGBColor(&tmpcol, uint8(startcol.red-(i*rstep)),
uint8(startcol.green-(i*gstep)),
uint8(startcol.blue-(i*bstep)));
layerdata.highcolor=tmpcol;
driver->StrokeLine(BPoint(r.left,r.top+i),
BPoint(r.left+i,r.top),&layerdata,(int8*)&solidhigh);
SetRGBColor(&tmpcol, uint8(halfcol.red-(i*rstep)),
uint8(halfcol.green-(i*gstep)),
uint8(halfcol.blue-(i*bstep)));
layerdata.highcolor=tmpcol;
driver->StrokeLine(BPoint(r.left+steps,r.top+i),
BPoint(r.left+i,r.top+steps),&layerdata,(int8*)&solidhigh);
}
// layerdata.highcolor=startcol;
// driver->FillRect(r,&layerdata,(int8*)&solidhigh);
layerdata.highcolor=frame_lowcol;
driver->StrokeRect(r,&layerdata,(int8*)&solidhigh);
}
void BeDecorator::_DrawFrame(BRect rect)
{
// Duh, draws the window frame, I think. ;)
if(look==WLOOK_NO_BORDER)
return;
BRect r=borderrect;
layerdata.highcolor=frame_midcol;
driver->StrokeLine(BPoint(r.left,r.top),BPoint(r.right-1,r.top),
&layerdata,(int8*)&solidhigh);
layerdata.highcolor=frame_lowcol;
driver->StrokeLine(BPoint(r.left,r.top),BPoint(r.left,r.bottom),
&layerdata,(int8*)&solidhigh);
layerdata.highcolor=frame_lowercol;
driver->StrokeLine(BPoint(r.right,r.bottom),BPoint(r.right,r.top),
&layerdata,(int8*)&solidhigh);
layerdata.highcolor=frame_lowercol;
driver->StrokeLine(BPoint(r.right,r.bottom),BPoint(r.left,r.bottom),
&layerdata,(int8*)&solidhigh);
r.InsetBy(1,1);
layerdata.highcolor=frame_highercol;
driver->StrokeLine(BPoint(r.left,r.top),BPoint(r.right-1,r.top),
&layerdata,(int8*)&solidhigh);
layerdata.highcolor=frame_highercol;
driver->StrokeLine(BPoint(r.left,r.top),BPoint(r.left,r.bottom),
&layerdata,(int8*)&solidhigh);
layerdata.highcolor=frame_midcol;
driver->StrokeLine(BPoint(r.right,r.bottom),BPoint(r.right,r.top),
&layerdata,(int8*)&solidhigh);
layerdata.highcolor=frame_midcol;
driver->StrokeLine(BPoint(r.right,r.bottom),BPoint(r.left,r.bottom),
&layerdata,(int8*)&solidhigh);
r.InsetBy(1,1);
layerdata.highcolor=frame_highcol;
driver->StrokeRect(r,&layerdata,(int8*)&solidhigh);
r.InsetBy(1,1);
layerdata.highcolor=frame_lowercol;
driver->StrokeLine(BPoint(r.left,r.top),BPoint(r.right-1,r.top),
&layerdata,(int8*)&solidhigh);
layerdata.highcolor=frame_lowercol;
driver->StrokeLine(BPoint(r.left,r.top),BPoint(r.left,r.bottom),
&layerdata,(int8*)&solidhigh);
layerdata.highcolor=frame_highercol;
driver->StrokeLine(BPoint(r.right,r.bottom),BPoint(r.right,r.top),
&layerdata,(int8*)&solidhigh);
layerdata.highcolor=frame_highercol;
driver->StrokeLine(BPoint(r.right,r.bottom),BPoint(r.left,r.bottom),
&layerdata,(int8*)&solidhigh);
driver->StrokeRect(borderrect,&layerdata,(int8*)&solidhigh);
// Draw the resize thumb if we're supposed to
if(!(flags & NOT_RESIZABLE))
{
r=resizerect;
int32 w=r.IntegerWidth(), h=r.IntegerHeight();
// This code is strictly for B_DOCUMENT_WINDOW looks
if(look==WLOOK_DOCUMENT)
{
rgb_color halfcol, startcol, endcol;
float rstep,gstep,bstep,i;
int steps=(w<h)?w:h;
startcol=frame_highercol.GetColor32();
endcol=frame_lowercol.GetColor32();
halfcol=frame_highercol.MakeBlendColor(frame_lowercol,0.5).GetColor32();
rstep=(startcol.red-halfcol.red)/steps;
gstep=(startcol.green-halfcol.green)/steps;
bstep=(startcol.blue-halfcol.blue)/steps;
for(i=0;i<=steps; i++)
{
layerdata.highcolor.SetColor(uint8(startcol.red-(i*rstep)),
uint8(startcol.green-(i*gstep)),
uint8(startcol.blue-(i*bstep)));
driver->StrokeLine(BPoint(r.left,r.top+i),
BPoint(r.left+i,r.top),&layerdata,(int8*)&solidhigh);
layerdata.highcolor.SetColor(uint8(halfcol.red-(i*rstep)),
uint8(halfcol.green-(i*gstep)),
uint8(halfcol.blue-(i*bstep)));
driver->StrokeLine(BPoint(r.left+steps,r.top+i),
BPoint(r.left+i,r.top+steps),&layerdata,(int8*)&solidhigh);
}
layerdata.highcolor=frame_lowercol;
driver->StrokeRect(r,&layerdata,(int8*)&solidhigh);
}
else
{
layerdata.highcolor=frame_lowercol;
driver->StrokeLine(BPoint(r.right,r.top),BPoint(r.right-3,r.top),
&layerdata,(int8*)&solidhigh);
driver->StrokeLine(BPoint(r.left,r.bottom),BPoint(r.left,r.bottom-3),
&layerdata,(int8*)&solidhigh);
}
}
}
extern "C" float get_decorator_version(void)
{
return 1.00;
}
extern "C" Decorator *instantiate_decorator(BRect rect, int32 wlook, int32 wfeel, int32 wflags)
{
return new BeDecorator(rect,wlook,wfeel,wflags);
}

View File

@ -0,0 +1,44 @@
#ifndef _BEOS_DECORATOR_H_
#define _BEOS_DECORATOR_H_
#include <Region.h>
#include "Decorator.h"
class BeDecorator: public Decorator
{
public:
BeDecorator(BRect frame, int32 wlook, int32 wfeel, int32 wflags);
~BeDecorator(void);
void MoveBy(float x, float y);
void MoveBy(BPoint pt);
void ResizeBy(float x, float y);
void ResizeBy(BPoint pt);
void Draw(BRect r);
void Draw(void);
BRegion *GetFootprint(void);
click_type Clicked(BPoint pt, int32 buttons, int32 modifiers);
protected:
void _DrawClose(BRect r);
void _DrawFrame(BRect r);
void _DrawTab(BRect r);
void _DrawTitle(BRect r);
void _DrawZoom(BRect r);
void _DoLayout(void);
void _SetFocus(void);
void DrawBlendedRect(BRect r, bool down);
uint32 taboffset;
RGBColor tab_highcol, tab_lowcol;
RGBColor button_highcol, button_lowcol;
RGBColor frame_highcol, frame_midcol, frame_lowcol, frame_highercol,
frame_lowercol;
RGBColor textcol;
uint64 solidhigh, solidlow;
bool slidetab;
int textoffset;
};
#endif

View File

@ -0,0 +1,87 @@
#include <stdio.h>
#include "ColorSet.h"
ColorSet::ColorSet(void)
{
}
ColorSet::ColorSet(const ColorSet &cs)
{
panel_background=cs.panel_background;
panel_text=cs.panel_text;
document_background=cs.document_background;
document_text=cs.document_text;
control_background=cs.control_background;
control_text=cs.control_text;
control_border=cs.control_border;
control_highlight=cs.control_highlight;
tooltip_background=cs.tooltip_background;
tooltip_text=cs.tooltip_text;
menu_background=cs.menu_background;
menu_selected_background=cs.menu_selected_background;
menu_text=cs.menu_text;
menu_selected_text=cs.menu_selected_text;
menu_separator_high=cs.menu_separator_high;
menu_separator_low=cs.menu_separator_low;
menu_triggers=cs.menu_triggers;
window_tab=cs.window_tab;
window_tab_text=cs.window_tab_text;
keyboard_navigation=cs.keyboard_navigation;
desktop=cs.desktop;
}
ColorSet & ColorSet::operator=(const ColorSet &cs)
{
SetColors(cs);
return *this;
}
void ColorSet::SetColors(const ColorSet &cs)
{
panel_background=cs.panel_background;
panel_text=cs.panel_text;
document_background=cs.document_background;
document_text=cs.document_text;
control_background=cs.control_background;
control_text=cs.control_text;
control_border=cs.control_border;
control_highlight=cs.control_highlight;
tooltip_background=cs.tooltip_background;
tooltip_text=cs.tooltip_text;
menu_background=cs.menu_background;
menu_selected_background=cs.menu_selected_background;
menu_text=cs.menu_text;
menu_selected_text=cs.menu_selected_text;
menu_separator_high=cs.menu_separator_high;
menu_separator_low=cs.menu_separator_low;
menu_triggers=cs.menu_triggers;
window_tab=cs.window_tab;
window_tab_text=cs.window_tab_text;
keyboard_navigation=cs.keyboard_navigation;
desktop=cs.desktop;
}
void ColorSet::PrintToStream(void)
{
printf("panel_background "); panel_background.PrintToStream();
printf("panel_text "); panel_text.PrintToStream();
printf("document_background "); document_background.PrintToStream();
printf("document_text "); document_text.PrintToStream();
printf("control_background "); control_background.PrintToStream();
printf("control_text "); control_text.PrintToStream();
printf("control_border "); control_border.PrintToStream();
printf("control_highlight "); control_highlight.PrintToStream();
printf("tooltip_background "); tooltip_background.PrintToStream();
printf("tooltip_text "); tooltip_text.PrintToStream();
printf("menu_background "); menu_background.PrintToStream();
printf("menu_selected_background "); menu_selected_background.PrintToStream();
printf("menu_text "); menu_text.PrintToStream();
printf("menu_selected_text "); menu_selected_text.PrintToStream();
printf("menu_separator_high "); menu_separator_high.PrintToStream();
printf("menu_separator_low "); menu_separator_low.PrintToStream();
printf("menu_triggers "); menu_triggers.PrintToStream();
printf("window_tab "); window_tab.PrintToStream();
printf("window_tab_text "); window_tab_text.PrintToStream();
printf("keyboard_navigation "); keyboard_navigation.PrintToStream();
printf("desktop "); desktop.PrintToStream();
}

View File

@ -0,0 +1,101 @@
#include "ColorUtils.h"
#include <stdio.h>
#include <stdlib.h>
//#define DEBUG_COLOR_UTILS
void SetRGBColor(rgb_color *col,uint8 r, uint8 g, uint8 b, uint8 a=255)
{
col->red=r;
col->green=g;
col->blue=b;
col->alpha=a;
}
uint8 FindClosestColor(rgb_color *palette, rgb_color color)
{
// We will be passed a 256-color palette and a 24-bit color
uint16 cindex=0,cdelta=765,delta=765;
rgb_color *c;
for(uint16 i=0;i<256;i++)
{
c=&(palette[i]);
delta=abs(c->red-color.red)+abs(c->green-color.green)+
abs(c->blue-color.blue);
if(delta==0)
{
cindex=i;
break;
}
if(delta<cdelta)
{
cindex=i;
cdelta=delta;
}
}
#ifdef DEBUG_COLOR_UTILS
printf("FindClosestColor( {%u,%u,%u,%u} ) : {%u,%u,%u,%u}\n",
color.red,color.green,color.blue,color.alpha,
palette[cindex].red,palette[cindex].green,palette[cindex].blue,palette[cindex].alpha);
#endif
return (uint8)cindex;
}
uint16 FindClosestColor16(rgb_color color)
{
printf("FindClosestColor16 unimplemented\n");
return 0;
}
rgb_color MakeBlendColor(rgb_color col, rgb_color col2, float position)
{
rgb_color newcol={0,0,0,0};
float mod=0;
int16 delta;
if(position<0 || position>1)
return newcol;
delta=int16(col2.red)-int16(col.red);
mod=col.red + (position * delta);
newcol.red=uint8(mod);
if(mod>255 )
newcol.red=255;
if(mod<0 )
newcol.red=0;
delta=int16(col2.green)-int16(col.green);
mod=col.green + (position * delta);
newcol.green=uint8(mod);
if(mod>255 )
newcol.green=255;
if(mod<0 )
newcol.green=0;
delta=int16(col2.blue)-int16(col.blue);
mod=col.blue + (position * delta);
newcol.blue=uint8(mod);
if(mod>255 )
newcol.blue=255;
if(mod<0 )
newcol.blue=0;
delta=int8(col2.alpha)-int8(col.alpha);
mod=col.alpha + (position * delta);
newcol.alpha=uint8(mod);
if(mod>255 )
newcol.alpha=255;
if(mod<0 )
newcol.alpha=0;
#ifdef DEBUG_COLOR_UTILS
printf("MakeBlendColor( {%u,%u,%u,%u}, {%u,%u,%u,%u}, %f) : {%u,%u,%u,%u}\n",
col.red,col.green,col.blue,col.alpha,
col2.red,col2.green,col2.blue,col2.alpha,
position,
newcol.red,newcol.green,newcol.blue,newcol.alpha);
#endif
return newcol;
}

View File

@ -0,0 +1,20 @@
#ifndef COLORUTILS_H_
#define COLORUTILS_H_
#include <GraphicsDefs.h>
// Quick assignment for rgb_color structs
void SetRGBColor(rgb_color *col,uint8 r, uint8 g, uint8 b, uint8 a=255);
// Given a color palette, returns the index of the closest match to
// the color passed to it. Alpha values are not considered
uint8 FindClosestColor(rgb_color *palette, rgb_color color);
uint16 FindClosestColor16(rgb_color color);
// Function which could be used to calculate gradient colors. Position is
// a floating point number such that 0.0 <= position <= 1.0. Any number outside
// this range will cause the function to fail and return the color (0,0,0,0)
// Alpha components are included in the calculations. 0 yields color #1
// and 1 yields color #2.
rgb_color MakeBlendColor(rgb_color col, rgb_color col2, float position);
#endif

View File

@ -0,0 +1,222 @@
#include <iostream.h>
#include <stdio.h>
#include "DebugTools.h"
void PrintStatusToStream(status_t value)
{
// Function which simply translates a returned status code into a string
// and dumps it to stdout
cout << "Status: " << TranslateStatusToString(value).String() << endl << flush;
}
BString TranslateStatusToString(status_t value)
{
BString outstr;
switch(value)
{
case B_OK:
outstr="B_OK ";
break;
case B_NAME_NOT_FOUND:
outstr="B_NAME_NOT_FOUND ";
break;
case B_BAD_VALUE:
outstr="B_BAD_VALUE ";
break;
case B_ERROR:
outstr="B_ERROR ";
break;
case B_TIMED_OUT:
outstr="B_TIMED_OUT ";
break;
case B_NO_MORE_PORTS:
outstr="B_NO_MORE_PORTS ";
break;
case B_WOULD_BLOCK:
outstr="B_WOULD_BLOCK ";
break;
case B_BAD_PORT_ID:
outstr="B_BAD_PORT_ID ";
break;
case B_BAD_TEAM_ID:
outstr="B_BAD_TEAM_ID ";
break;
default:
outstr="undefined status value in debugtools::PrintStatusToStream() ";
break;
}
return BString(outstr);
}
void PrintColorSpaceToStream(color_space value)
{
// Dump a color space to cout
BString outstr;
switch(value)
{
case B_RGB32:
outstr="B_RGB32 ";
break;
case B_RGBA32:
outstr="B_RGBA32 ";
break;
case B_RGB32_BIG:
outstr="B_RGB32_BIG ";
break;
case B_RGBA32_BIG:
outstr=" ";
break;
case B_UVL32:
outstr="B_UVL32 ";
break;
case B_UVLA32:
outstr="B_UVLA32 ";
break;
case B_LAB32:
outstr="B_LAB32 ";
break;
case B_LABA32:
outstr="B_LABA32 ";
break;
case B_HSI32:
outstr="B_HSI32 ";
break;
case B_HSIA32:
outstr="B_HSIA32 ";
break;
case B_HSV32:
outstr="B_HSV32 ";
break;
case B_HSVA32:
outstr="B_HSVA32 ";
break;
case B_HLS32:
outstr="B_HLS32 ";
break;
case B_HLSA32:
outstr="B_HLSA32 ";
break;
case B_CMY32:
outstr="B_CMY32";
break;
case B_CMYA32:
outstr="B_CMYA32 ";
break;
case B_CMYK32:
outstr="B_CMYK32 ";
break;
case B_RGB24_BIG:
outstr="B_RGB24_BIG ";
break;
case B_RGB24:
outstr="B_RGB24 ";
break;
case B_LAB24:
outstr="B_LAB24 ";
break;
case B_UVL24:
outstr="B_UVL24 ";
break;
case B_HSI24:
outstr="B_HSI24 ";
break;
case B_HSV24:
outstr="B_HSV24 ";
break;
case B_HLS24:
outstr="B_HLS24 ";
break;
case B_CMY24:
outstr="B_CMY24 ";
break;
case B_GRAY1:
outstr="B_GRAY1 ";
break;
case B_CMAP8:
outstr="B_CMAP8 ";
break;
case B_GRAY8:
outstr="B_GRAY8 ";
break;
case B_YUV411:
outstr="B_YUV411 ";
break;
case B_YUV420:
outstr="B_YUV420 ";
break;
case B_YCbCr422:
outstr="B_YCbCr422 ";
break;
case B_YCbCr411:
outstr="B_YCbCr411 ";
break;
case B_YCbCr420:
outstr="B_YCbCr420 ";
break;
case B_YUV422:
outstr="B_YUV422 ";
break;
case B_YUV9:
outstr="B_YUV9 ";
break;
case B_YUV12:
outstr="B_YUV12 ";
break;
case B_RGB15:
outstr="B_RGB15 ";
break;
case B_RGBA15:
outstr="B_RGBA15 ";
break;
case B_RGB16:
outstr="B_RGB16 ";
break;
case B_RGB16_BIG:
outstr="B_RGB16_BIG ";
break;
case B_RGB15_BIG:
outstr="B_RGB15_BIG ";
break;
case B_RGBA15_BIG:
outstr="B_RGBA15_BIG ";
break;
case B_YCbCr444:
outstr="B_YCbCr444 ";
break;
case B_YUV444:
outstr="B_YUV444 ";
break;
case B_NO_COLOR_SPACE:
outstr="B_NO_COLOR_SPACE ";
break;
default:
outstr="Undefined color space ";
break;
}
cout << "Color Space: " << outstr.String() << flush;
}
void TranslateMessageCodeToStream(int32 code)
{
// Used to translate BMessage message codes back to a character
// format
cout << "'"
<< (char)((code & 0xFF000000) >> 24)
<< (char)((code & 0x00FF0000) >> 16)
<< (char)((code & 0x0000FF00) >> 8)
<< (char)((code & 0x000000FF)) << "' ";
}
void PrintMessageCode(int32 code)
{
// Used to translate BMessage message codes back to a character
// format
printf("Message code %c%c%c%c\n",
(char)((code & 0xFF000000) >> 24),
(char)((code & 0x00FF0000) >> 16),
(char)((code & 0x0000FF00) >> 8),
(char)((code & 0x000000FF)) );
}

View File

@ -0,0 +1,13 @@
#ifndef _DEBUGTOOLS_H_
#define _DEBUGTOOLS_H_
#include <SupportDefs.h>
#include <GraphicsDefs.h>
#include <String.h>
void PrintColorSpaceToStream(color_space value);
void TranslateMessageCodeToStream(int32 code);
void PrintMessageCode(int32 code);
BString TranslateStatusToString(status_t value);
#endif

View File

@ -0,0 +1,242 @@
#include "Decorator.h"
#include <string.h>
Decorator::Decorator(BRect rect, int32 wlook, int32 wfeel, int32 wflags)
{
close_state=false;
minimize_state=false;
zoom_state=false;
title_string=NULL;
driver=NULL;
closerect.Set(0,0,1,1);
zoomrect.Set(0,0,1,1);
minimizerect.Set(0,0,1,1);
resizerect.Set(0,0,1,1);
frame=rect;
tabrect.Set(rect.left,rect.top,rect.right, rect.top+((rect.bottom-rect.top)/4));
look=wlook;
feel=wfeel;
flags=wflags;
colors=new ColorSet();
}
Decorator::~Decorator(void)
{
if(colors!=NULL)
{
delete colors;
colors=NULL;
}
if(title_string)
delete title_string;
}
void Decorator::SetColors(ColorSet cset)
{
colors->SetColors(cset);
}
void Decorator::SetDriver(DisplayDriver *d)
{
driver=d;
}
void Decorator::SetClose(bool is_down)
{
close_state=is_down;
}
void Decorator::SetMinimize(bool is_down)
{
zoom_state=is_down;
}
void Decorator::SetZoom(bool is_down)
{
minimize_state=is_down;
}
void Decorator::SetFlags(int32 wflags)
{
flags=wflags;
}
void Decorator::SetFeel(int32 wfeel)
{
feel=wfeel;
}
void Decorator::SetLook(int32 wlook)
{
look=wlook;
}
bool Decorator::GetClose(void)
{
return close_state;
}
bool Decorator::GetMinimize(void)
{
return minimize_state;
}
bool Decorator::GetZoom(void)
{
return zoom_state;
}
int32 Decorator::GetLook(void)
{
return look;
}
int32 Decorator::GetFeel(void)
{
return feel;
}
int32 Decorator::GetFlags(void)
{
return flags;
}
void Decorator::SetTitle(const char *string)
{
if(string)
{
size_t size=strlen(string);
if(!(size>0))
return;
delete title_string;
title_string=new char[size];
strcpy(title_string,string);
}
else
{
delete title_string;
title_string=NULL;
}
}
const char *Decorator::GetTitle(void)
{
return title_string;
}
void Decorator::SetFocus(bool is_active)
{
has_focus=is_active;
_SetFocus();
}
/*
void Decorator::SetFont(SFont *sf)
{
}
*/
void Decorator::_ClipTitle(void)
{
}
//-------------------------------------------------------------------------
// Virtual Methods
//-------------------------------------------------------------------------
void Decorator::MoveBy(float x, float y)
{
}
void Decorator::MoveBy(BPoint pt)
{
}
void Decorator::ResizeBy(float x, float y)
{
}
void Decorator::ResizeBy(BPoint pt)
{
}
void Decorator::Draw(BRect r)
{
_DrawTab(r & tabrect);
_DrawFrame(r & frame);
}
void Decorator::Draw(void)
{
_DrawTab(tabrect);
_DrawFrame(frame);
}
void Decorator::DrawClose(void)
{
_DrawClose(closerect);
}
void Decorator::DrawFrame(void)
{
_DrawFrame(frame);
}
void Decorator::DrawMinimize(void)
{
_DrawTab(minimizerect);
}
void Decorator::DrawTab(void)
{
_DrawTab(tabrect);
_DrawZoom(zoomrect);
_DrawMinimize(minimizerect);
_DrawTitle(tabrect);
_DrawClose(closerect);
}
void Decorator::DrawTitle(void)
{
_DrawTitle(tabrect);
}
void Decorator::DrawZoom(void)
{
_DrawZoom(zoomrect);
}
void Decorator::_DrawClose(BRect r)
{
}
void Decorator::_DrawFrame(BRect r)
{
}
void Decorator::_DrawMinimize(BRect r)
{
}
void Decorator::_DrawTab(BRect r)
{
}
void Decorator::_DrawTitle(BRect r)
{
}
void Decorator::_DrawZoom(BRect r)
{
}
/*
SRegion Decorator::GetFootprint(void)
{
}
*/
click_type Decorator::Clicked(BPoint pt, int32 buttons, int32 modifiers)
{
return CLICK_NONE;
}

View File

@ -0,0 +1,121 @@
#ifndef _DECORATOR_H_
#define _DECORATOR_H_
#include <SupportDefs.h>
#include <Rect.h>
#include "ColorSet.h"
#include "LayerData.h"
class Layer;
class DisplayDriver;
typedef enum { CLICK_NONE=0, CLICK_ZOOM, CLICK_CLOSE, CLICK_MINIMIZE,
CLICK_TAB, CLICK_DRAG, CLICK_MOVETOBACK, CLICK_MOVETOFRONT,
CLICK_RESIZE, CLICK_RESIZE_L, CLICK_RESIZE_T,
CLICK_RESIZE_R, CLICK_RESIZE_B, CLICK_RESIZE_LT, CLICK_RESIZE_RT,
CLICK_RESIZE_LB, CLICK_RESIZE_RB } click_type;
// Definitions which are used in place of including Window.h
// window_look and window_feel are enumerated types, so we convert them
// to uint32's in order to ensure a constant size when sending via PortLink
// instead of depending on magic numbers in the header file.
#define WLOOK_NO_BORDER 0
#define WLOOK_BORDERED 1
#define WLOOK_TITLED 2
#define WLOOK_DOCUMENT 3
#define WLOOK_MODAL 4
#define WLOOK_FLOATING 5
#define WFEEL_NORMAL 0
#define WFEEL_MODAL_SUBSET 1
#define WFEEL_MODAL_APP 2
#define WFEEL_MODAL_WINDOW 3
#define WFEEL_FLOATING_SUBSET 4
#define WFEEL_FLOATING_APP 5
#define WFEEL_FLOATING_WINDOW 6
#define NOT_MOVABLE 0x00000001
#define NOT_CLOSABLE 0x00000020
#define NOT_ZOOMABLE 0x00000040
#define NOT_MINIMIZABLE 0x00004000
#define NOT_RESIZABLE 0x00000002
#define NOT_H_RESIZABLE 0x00000004
#define NOT_V_RESIZABLE 0x00000008
#define AVOID_FRONT 0x00000080
#define AVOID_FOCUS 0x00002000
#define WILL_ACCEPT_FIRST_CLICK 0x00000010
#define OUTLINE_RESIZE 0x00001000
#define NO_WORKSPACE_ACTIVATION 0x00000100
#define NOT_ANCHORED_ON_ACTIVATE 0x00020000
#define ASYNCHRONOUS_CONTROLS 0x00080000
#define QUIT_ON_WINDOW_CLOSE 0x00100000
class Decorator
{
public:
Decorator(BRect rect, int32 wlook, int32 wfeel, int32 wflags);
virtual ~Decorator(void);
void SetColors(ColorSet cset);
void SetDriver(DisplayDriver *d);
void SetClose(bool is_down);
void SetMinimize(bool is_down);
void SetZoom(bool is_down);
void SetFlags(int32 wflags);
void SetFeel(int32 wfeel);
void SetLook(int32 wlook);
bool GetClose(void);
bool GetMinimize(void);
bool GetZoom(void);
int32 GetLook(void);
int32 GetFeel(void);
int32 GetFlags(void);
void SetTitle(const char *string);
void SetFocus(bool is_active);
bool GetFocus(void) { return has_focus; };
const char *GetTitle(void);
// void SetFont(SFont *sf);
void _ClipTitle(void);
ColorSet GetColors(void) { if(colors) return *colors; else return ColorSet(); }
virtual void MoveBy(float x, float y);
virtual void MoveBy(BPoint pt);
virtual void ResizeBy(float x, float y);
virtual void ResizeBy(BPoint pt);
virtual void Draw(BRect r);
virtual void Draw(void);
virtual void DrawClose(void);
virtual void DrawFrame(void);
virtual void DrawMinimize(void);
virtual void DrawTab(void);
virtual void DrawTitle(void);
virtual void DrawZoom(void);
//virtual SRegion GetFootprint(void);
virtual click_type Clicked(BPoint pt, int32 buttons, int32 modifiers);
protected:
virtual void _DrawClose(BRect r);
virtual void _DrawFrame(BRect r);
virtual void _DrawMinimize(BRect r);
virtual void _DrawTab(BRect r);
virtual void _DrawTitle(BRect r);
virtual void _DrawZoom(BRect r);
virtual void _SetFocus(void)=0;
virtual void _DoLayout(void)=0;
ColorSet *colors;
int32 look, feel, flags;
DisplayDriver *driver;
LayerData layerdata;
BRect zoomrect,closerect,minimizerect,tabrect,frame,
resizerect,borderrect;
private:
bool close_state, zoom_state, minimize_state;
bool has_focus;
char *title_string;
};
typedef float get_version(void);
typedef Decorator *create_decorator(BRect rect, int32 wlook, int32 wfeel, int32 wflags);
#endif

View File

@ -0,0 +1,610 @@
/*
Desktop.cpp:
Code necessary to handle the Desktop, defined as the collection of workspaces.
*/
//#define DEBUG_WORKSPACES
#include <List.h>
#include <Path.h>
#include <GraphicsCard.h>
#include <stdio.h>
#include <Locker.h>
#include <File.h>
#include <String.h>
#include "ServerProtocol.h"
#include "ColorUtils.h"
#include "SystemPalette.h"
#include "ServerWindow.h"
#include "ServerCursor.h"
#include "Layer.h"
#include "DisplayDriver.h"
#include "ViewDriver.h"
#include "ScreenDriver.h"
#include "Desktop.h"
#include "WindowBorder.h"
#include "ColorSet.h"
#include "RGBColor.h"
class ServerWindow;
class ServerBitmap;
class Workspace;
rgb_color GetColorFromMessage(BMessage *msg, const char *name, int32 index=0);
// Temporarily necessary. Will not be present in the app_server.
int8 default_cursor[]={
16,1,0,0,
// data
0xff, 0x80, 0x80, 0x80, 0x81, 0x00, 0x80, 0x80, 0x80, 0x40, 0x80, 0x80, 0x81, 0x00, 0xa2, 0x00,
0xd4, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// mask
0xff, 0x80, 0xff, 0x80, 0xff, 0x00, 0xff, 0x80, 0xff, 0xc0, 0xff, 0x80, 0xff, 0x00, 0xfe, 0x00,
0xdc, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
//--------------------GLOBALS-------------------------
uint32 workspace_count, active_workspace;
BList *desktop;
ServerCursor *startup_cursor;
Workspace *pactive_workspace;
DisplayDriver *gfxdriver;
int32 token_count=-1;
BLocker *workspacelock;
BLocker *layerlock;
BLocker *colorlock;
UpdateNode *upnode;
ColorSet *gui_colors;
//----------------------------------------------------
//-------------------INTERNAL CLASS DEFS--------------
class Workspace
{
public:
Workspace(void);
Workspace(BPath imagepath);
~Workspace();
void SetBGColor(rgb_color col);
rgb_color BGColor(void);
thread_id tid;
RootLayer *toplayer;
BList focuslist;
rgb_color bgcolor;
screen_info screendata,
olddata;
};
DisplayDriver *get_gfxdriver(void)
{
return gfxdriver;
}
Workspace::Workspace(void)
{
workspace_count++;
// default values
focuslist.MakeEmpty();
bgcolor.red=51;
bgcolor.green=102;
bgcolor.blue=160;
screendata.mode=B_CMAP8;
screendata.spaces=B_8_BIT_640x480;
screendata.refresh_rate=60.0;
screendata.min_refresh_rate=60.0;
screendata.max_refresh_rate=60.0;
screendata.h_position=(uchar)50;
screendata.v_position=(uchar)50;
screendata.h_size=(uchar)50;
screendata.v_size=(uchar)50;
olddata=screendata;
// We need one top layer for each workspace times the number of monitors - ick.
// Currently, we only have 1 monitor. *Whew*
char wspace_name[128];
sprintf(wspace_name,"workspace %ld root",workspace_count);
toplayer=new RootLayer(BRect(0,0,639,439),wspace_name);
}
Workspace::~Workspace(void)
{
workspace_count--;
toplayer->PruneTree();
}
void Workspace::SetBGColor(rgb_color col)
{
bgcolor=col;
toplayer->SetColor(col);
#ifdef DEBUG_WORKSPACES
printf("Workspace::SetBGColor(%d,%d,%d,%d)\n",bgcolor.red,bgcolor.green,
bgcolor.blue,bgcolor.alpha);
#endif
}
rgb_color Workspace::BGColor(void)
{
return bgcolor;
}
//---------------------------------------------------
//-----------------GLOBAL FUNCTION DEFS---------------
void init_desktop(int8 workspaces)
{
#ifdef DEBUG_WORKSPACES
printf("init_desktop(%d)\n",workspaces);
#endif
workspace_count=workspaces;
if(workspace_count==0)
workspace_count++;
// Instantiate and initialize display driver
// gfxdriver=new ViewDriver();
// gfxdriver=new SecondDriver();
gfxdriver=new ScreenDriver();
gfxdriver->Initialize();
workspacelock=new BLocker();
layerlock=new BLocker();
colorlock=new BLocker();
gui_colors=new ColorSet;
#ifdef DEBUG_WORKSPACES
printf("Driver %s\n", (gfxdriver->IsInitialized()==true)?"initialized":"NOT initialized");
#endif
desktop=new BList(0);
// Create the workspaces we're supposed to have
for(int8 i=0; i<workspaces; i++)
desktop->AddItem(new Workspace());
// Load workspace preferences here
// We're going to punch in some hardcoded settings for testing purposes.
// There are 3 workspaces hardcoded in for now, but we'll only use the
// second one.
Workspace *wksp=(Workspace*)desktop->ItemAt(1);
if(wksp!=NULL) // in case I forgot something
{
rgb_color bcol;
SetRGBColor(&bcol,0,200,236);
// SetRGBColor(&(wksp->bgcolor),0,200,236);
wksp->SetBGColor(bcol);
screen_info *tempsd=&(wksp->screendata);
tempsd->mode=B_CMAP8;
tempsd->spaces=B_8_BIT_800x600;
tempsd->frame.Set(0,0,799,599);
}
else
printf("DW goofed on the workspace index :P\n");
// Activate workspace 0
pactive_workspace=(Workspace *)desktop->ItemAt(0);
pactive_workspace->screendata.spaces=B_32_BIT_640x480;
gfxdriver->SetMode(pactive_workspace->screendata.spaces);
// Clear the screen
pactive_workspace->toplayer->SetColor(RGBColor(80,85,152));
// gfxdriver->Clear(pactive_workspace->toplayer->GetColor());
startup_cursor=new ServerCursor(default_cursor);
gfxdriver->SetCursor(startup_cursor);
gfxdriver->ShowCursor();
pactive_workspace->toplayer->SetVisible(true);
#ifdef DEBUG_WORKSPACES
printf("Desktop initialized\n");
#endif
}
void shutdown_desktop(void)
{
int32 i,count=desktop->CountItems();
Workspace *w;
for(i=0;i<count;i++)
{
w=(Workspace*)desktop->ItemAt(i);
if(w!=NULL)
delete w;
}
desktop->MakeEmpty();
delete desktop;
gfxdriver->Shutdown();
delete gfxdriver;
delete workspacelock;
delete layerlock;
delete colorlock;
delete startup_cursor;
delete gui_colors;
}
int32 CountWorkspaces(void)
{
#ifdef DEBUG_WORKSPACES
printf("CountWorkspaces() returned %ld\n",workspace_count);
#endif
return workspace_count;
}
void SetWorkspaceCount(uint32 count)
{
if(count<0)
{
#ifdef DEBUG_WORKSPACES
printf("SetWorkspaceCount(value<0) - DOH!\n");
#endif
return;
}
if(count==workspace_count)
return;
// Activate last workspace in new set if we're using one to be nuked
if(count<active_workspace)
activate_workspace(count);
if(count < workspace_count)
{
for(uint32 i=count;i<workspace_count;i++)
{
if(desktop->ItemAt(i)!=NULL)
{
delete (Workspace*)desktop->ItemAt(i);
desktop->RemoveItem(i);
}
}
}
else
{
// count > workspace_count here
// Once we have default workspace preferences which can be set by the
// user, we'll end up having to initialize newly-added workspaces to that
// data. In the mean time, the defaults in the constructor will do. :)
for(uint32 i=count;i<workspace_count;i++)
{
desktop->AddItem(new Workspace());
}
}
// don't forget to update our global!
workspace_count=desktop->CountItems();
#ifdef DEBUG_WORKSPACES
printf("SetWorkspaceCount(%ld)\n",workspace_count);
#endif
}
int32 CurrentWorkspace(void)
{
#ifdef DEBUG_WORKSPACES
printf("CurrentWorkspace() returned %ld\n",active_workspace);
#endif
return active_workspace;
}
void ActivateWorkspace(uint32 workspace)
{
// In order to change workspaces, we'll need to make all the necessary
// changes to the screen to fit the new one, such as resolution,
// background color, color depth, refresh rate, etc.
if(workspace>workspace_count || workspace<0)
return;
Workspace *proposed=(Workspace *)desktop->ItemAt(workspace);
if(proposed==NULL)
return;
// Here's where we update all the screen stuff
// if(pactive_workspace->screendata.spaces != proposed->screendata.spaces)
// {
gfxdriver->SetMode(proposed->screendata.spaces);
// gfxdriver->Clear(proposed->bgcolor);
pactive_workspace->toplayer->SetVisible(false);
proposed->toplayer->SetVisible(true);
// }
// more if != then change code goes here. Currently, a lot of the code which
// uses this stuff is not implemented, so it's kind of moot. However, when we
// use the real graphics HW, it'll become important.
// actually set our active workspace data to reflect the change in workspaces
pactive_workspace=proposed;
active_workspace=workspace;
#ifdef DEBUG_WORKSPACES
printf("ActivateWorkspace(%ld)\n",active_workspace);
#endif
}
const color_map *SystemColors(void)
{
return (const color_map *)&system_palette;
}
status_t SetScreenSpace(uint32 index, uint32 res, bool stick = true)
{
#ifdef DEBUG_WORKSPACES
printf("SetScreenSpace(%ld,%lu, %s)\n",index,res,(stick==true)?"true":"false");
#endif
if(index>workspace_count-1)
{
printf("SetScreenSpace was passed invalid workspace value %ld\n",index);
return B_ERROR;
}
if(res>0x800000) // the last "normal" screen mode defined in GraphicsDefs.h
{
printf("SetScreenSpace was passed invalid screen value %lu\n",res);
return B_ERROR;
}
// When we actually use app_server preferences, we'll save the screen mode to
// the preferences so that we use this mode next boot. For now, we treat stick==false
if(stick==true)
{
// save the screen data here
}
if(index==active_workspace)
{
gfxdriver->SetMode(res);
// gfxdriver->Clear(pactive_workspace->bgcolor);
}
else
{
// just set the workspace's data here. right now, do nothing.
}
return B_OK;
}
int32 GetViewToken(void)
{
// Used to generate view and layer tokens
return ++token_count;
}
void AddWindowToDesktop(ServerWindow *win,uint32 workspace)
{
// Adds the top layer of each window to the root layer in the specified workspace.
// Note that in calling AddChild, a redraw is invoked
if(!win || workspace>workspace_count-1)
return;
workspacelock->Lock();
Workspace *w=(Workspace *)desktop->ItemAt(workspace);
if(w)
{
// a check for the B_CURRENT_WORKSPACE or B_ALL_WORKSPACES specifiers will
// go here later
w->toplayer->AddChild(win->winborder);
}
workspacelock->Unlock();
}
void RemoveWindowFromDesktop(ServerWindow *win)
{
// A little more time-consuming than AddWindow
if(!win)
return;
workspacelock->Lock();
// a check for the B_CURRENT_WORKSPACE or B_ALL_WORKSPACES specifiers will
// go here later
// If the window belongs on only 1 workspace, calling RemoveSelf is the most
// elegant solution.
win->winborder->RemoveSelf();
workspacelock->Unlock();
}
Layer *GetRootLayer(void)
{
layerlock->Lock();
Layer *lay=(workspace_count>0)?pactive_workspace->toplayer:NULL;
layerlock->Unlock();
return lay;
}
ServerWindow *GetActiveWindow(int32 workspace)
{
Layer *root=GetRootLayer();
if(!root)
return NULL;
Layer *lay=root->topchild, *nextlay;
while(lay!=NULL)
{
if(lay->serverwin && lay->serverwin->HasFocus())
return lay->serverwin;
nextlay=lay->lowersibling;
lay=nextlay;
}
return NULL;
}
rgb_color GetColorFromMessage(BMessage *msg, const char *name, int32 index=0)
{
// Simple function to do the dirty work of getting an rgb_color from
// a message
rgb_color *col,rcolor={0,0,0,0};
ssize_t size;
if(msg->FindData(name,(type_code)'RGBC',index,(const void**)&col,&size)==B_OK)
rcolor=*col;
return rcolor;
}
void SetGUIColor(color_which attr, RGBColor color)
{
colorlock->Lock();
switch(attr)
{
case B_PANEL_BACKGROUND_COLOR:
{
gui_colors->panel_background=color;
break;
}
case B_MENU_BACKGROUND_COLOR:
{
gui_colors->menu_background=color;
break;
}
case B_MENU_SELECTION_BACKGROUND_COLOR:
{
gui_colors->menu_selected_background=color;
break;
}
case B_MENU_ITEM_TEXT_COLOR:
{
gui_colors->menu_text=color;
break;
}
case B_MENU_SELECTED_ITEM_TEXT_COLOR:
{
gui_colors->menu_selected_text=color;
break;
}
case B_WINDOW_TAB_COLOR:
{
gui_colors->window_tab=color;
break;
}
case B_KEYBOARD_NAVIGATION_COLOR:
{
gui_colors->keyboard_navigation=color;
break;
}
case B_DESKTOP_COLOR:
{
gui_colors->desktop=color;
break;
}
default:
break;
}
colorlock->Unlock();
}
RGBColor GetGUIColor(color_which attr)
{
colorlock->Lock();
RGBColor c;
switch(attr)
{
case B_PANEL_BACKGROUND_COLOR:
{
c=gui_colors->panel_background;
break;
}
case B_MENU_BACKGROUND_COLOR:
{
c=gui_colors->menu_background;
break;
}
case B_MENU_SELECTION_BACKGROUND_COLOR:
{
c=gui_colors->menu_selected_background;
break;
}
case B_MENU_ITEM_TEXT_COLOR:
{
c=gui_colors->menu_text;
break;
}
case B_MENU_SELECTED_ITEM_TEXT_COLOR:
{
c=gui_colors->menu_selected_text;
break;
}
case B_WINDOW_TAB_COLOR:
{
c=gui_colors->window_tab;
break;
}
case B_KEYBOARD_NAVIGATION_COLOR:
{
c=gui_colors->keyboard_navigation;
break;
}
case B_DESKTOP_COLOR:
{
c=gui_colors->desktop;
break;
}
default:
break;
}
colorlock->Unlock();
return c;
}
void SetGUIColors(ColorSet set)
{
colorlock->Lock();
*gui_colors=set;
colorlock->Unlock();
}
ColorSet GetGUIColors(void)
{
colorlock->Lock();
ColorSet cs(*gui_colors);
colorlock->Unlock();
return cs;
}
void LoadGUIColors(void)
{
// Load the current GUI color settings from a color set file.
BString path(SERVER_SETTINGS_DIR);
path+=COLOR_SETTINGS_NAME;
BFile file(path.String(),B_READ_ONLY);
BMessage msg;
if(file.InitCheck()==B_OK)
{
if(msg.Unflatten(&file)==B_OK)
{
// Just get the "official" GUI colors for now
gui_colors->panel_background=GetColorFromMessage(&msg,"PANEL_BACKGROUND");
gui_colors->menu_background=GetColorFromMessage(&msg,"MENU_BACKGROUND");
gui_colors->menu_selected_background=GetColorFromMessage(&msg,"MENU_SELECTION_BACKGROUND");
gui_colors->menu_text=GetColorFromMessage(&msg,"MENU_ITEM_TEXT");
gui_colors->menu_selected_text=GetColorFromMessage(&msg,"MENU_SELECTED_ITEM_TEXT");
gui_colors->window_tab=GetColorFromMessage(&msg,"WINDOW_TAB");
gui_colors->keyboard_navigation=GetColorFromMessage(&msg,"KEYBOARD_NAVIGATION");
gui_colors->desktop=GetColorFromMessage(&msg,"DESKTOP");
// fake the rest
}
else
printf("app_server couldn't get GUI color settings from %s%s. Resetting to defaults\n",
SERVER_SETTINGS_DIR,COLOR_SETTINGS_NAME);
}
else
printf("app_server couldn't open %s%s. Resetting GUI colors to defaults\n",
SERVER_SETTINGS_DIR,COLOR_SETTINGS_NAME);
}
// Another "just in case DW screws up again" section
#ifdef DEBUG_WORKSPACES
#undef DEBUG_WORKSPACES
#endif

View File

@ -0,0 +1,55 @@
#ifndef _OBDESKTOP_H_
#define _OBDESKTOP_H_
#include <InterfaceDefs.h>
#include <GraphicsDefs.h>
#include <Rect.h>
class RGBColor;
class ColorSet;
class DisplayDriver;
class ServerWindow;
class Layer;
void init_desktop(int8 workspaces);
void shutdown_desktop(void);
DisplayDriver *get_gfxdriver(void);
// Workspace access functions
int32 CountWorkspaces(void);
void SetWorkspaceCount(uint32 count);
int32 CurrentWorkspace(void);
void ActivateWorkspace(uint32 workspace);
const color_map *SystemColors(void);
status_t SetScreenSpace(uint32 index, uint32 res, bool stick=true);
void AddWindowToDesktop(ServerWindow *win,uint32 workspace);
void RemoveWindowFromDesktop(ServerWindow *win);
ServerWindow *GetActiveWindow(int32 workspace);
Layer *GetRootLayer(void);
int32 GetViewToken(void);
void LoadGUIColors(void);
void SetGUIColor(color_which attr, RGBColor color);
RGBColor GetGUIColor(color_which attr);
void SetGUIColors(ColorSet set);
ColorSet GetGUIColors(void);
typedef struct
{
color_space mode;
BRect frame;
uint32 spaces;
float min_refresh_rate;
float max_refresh_rate;
float refresh_rate;
uchar h_position;
uchar v_position;
uchar h_size;
uchar v_size;
} screen_info;
#endif

View File

@ -0,0 +1,176 @@
/*
DisplayDriver.cpp
Modular class to allow the server to not care what the ultimate output is
for graphics calls.
*/
#include "DisplayDriver.h"
#include "LayerData.h"
#include "ServerCursor.h"
DisplayDriver::DisplayDriver(void)
{
lock_sem=create_sem(1,"displaydriver_lock");
buffer_depth=0;
buffer_width=0;
buffer_height=0;
buffer_mode=-1;
}
DisplayDriver::~DisplayDriver(void)
{
delete_sem(lock_sem);
}
bool DisplayDriver::Initialize(void)
{
return false;
}
uint8 DisplayDriver::GetDepth(void)
{
return buffer_depth;
}
uint16 DisplayDriver::GetHeight(void)
{
return buffer_height;
}
uint16 DisplayDriver::GetWidth(void)
{
return buffer_width;
}
int32 DisplayDriver::GetMode(void)
{
return buffer_mode;
}
bool DisplayDriver::DumpToFile(const char *path)
{
return false;
}
bool DisplayDriver::IsCursorHidden(void)
{
return (is_cursor_hidden>0)?true:false;
}
void DisplayDriver::HideCursor(void)
{
SetCursorHidden(true);
}
void DisplayDriver::ShowCursor(void)
{
SetCursorHidden(false);
}
void DisplayDriver::ObscureCursor(void)
{
SetCursorObscured(true);
}
void DisplayDriver::SetCursor(ServerCursor *cursor)
{
}
//---------------------------------------------------------
// Private Methods
//---------------------------------------------------------
void DisplayDriver::Lock(void)
{
acquire_sem(lock_sem);
}
void DisplayDriver::Unlock(void)
{
release_sem(lock_sem);
}
void DisplayDriver::SetDepthInternal(uint8 d)
{
buffer_depth=d;
}
void DisplayDriver::SetHeightInternal(uint16 h)
{
buffer_height=h;
}
void DisplayDriver::SetWidthInternal(uint16 w)
{
buffer_width=w;
}
void DisplayDriver::SetModeInternal(int32 m)
{
buffer_mode=m;
}
void DisplayDriver::SetCursorHidden(bool state)
{
if(state)
{
is_cursor_hidden++;
cursor_state_changed=(is_cursor_hidden==1)?true:false;
}
else
{
if(is_cursor_hidden>0)
{
is_cursor_hidden--;
cursor_state_changed=(is_cursor_hidden==0)?true:false;
}
}
}
bool DisplayDriver::CursorStateChanged(void)
{
return cursor_state_changed;
}
bool DisplayDriver::IsCursorObscured(bool state)
{
return is_cursor_obscured;
}
void DisplayDriver::SetCursorObscured(bool state)
{
is_cursor_obscured=state;
}
//---------------------------------------------------------
// Empty Methods
//---------------------------------------------------------
void DisplayDriver::Shutdown(void) {}
void DisplayDriver::CopyBits(BRect src, BRect dest) {}
void DisplayDriver::DrawBitmap(ServerBitmap *bmp, BRect src, BRect dest) {}
void DisplayDriver::DrawChar(char c, BPoint pt) {}
//void DisplayDriver::DrawPicture(SPicture *pic, BPoint pt) {}
void DisplayDriver::DrawString(const char *string, int32 length, BPoint pt, LayerData *d, escapement_delta *delta=NULL) {}
void DisplayDriver::FillArc(BRect r, float angle, float span, LayerData *d, int8 *pat) {}
void DisplayDriver::FillBezier(BPoint *pts, LayerData *d, int8 *pat) {}
void DisplayDriver::FillEllipse(BRect r, LayerData *d, int8 *pat) {}
void DisplayDriver::FillPolygon(BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, int8 *pat) {}
void DisplayDriver::FillRect(BRect r, LayerData *d, int8 *pat) {}
void DisplayDriver::FillRoundRect(BRect r, float xrad, float yrad, LayerData *d, int8 *pat) {}
//void DisplayDriver::FillShape(SShape *sh, LayerData *d, int8 *pat) {}
void DisplayDriver::FillTriangle(BPoint *pts, BRect r, LayerData *d, int8 *pat) {}
void DisplayDriver::MoveCursorTo(float x, float y) {}
void DisplayDriver::InvertRect(BRect r) {}
void DisplayDriver::StrokeArc(BRect r, float angle, float span, LayerData *d, int8 *pat) {}
void DisplayDriver::StrokeBezier(BPoint *pts, LayerData *d, int8 *pat) {}
void DisplayDriver::StrokeEllipse(BRect r, LayerData *d, int8 *pat) {}
void DisplayDriver::StrokeLine(BPoint start, BPoint end, LayerData *d, int8 *pat) {}
void DisplayDriver::StrokePolygon(BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, int8 *pat, bool is_closed=true) {}
void DisplayDriver::StrokeRect(BRect r, LayerData *d, int8 *pat) {}
void DisplayDriver::StrokeRoundRect(BRect r, float xrad, float yrad, LayerData *d, int8 *pat) {}
//void DisplayDriver::StrokeShape(SShape *sh, LayerData *d, int8 *pat) {}
void DisplayDriver::StrokeTriangle(BPoint *pts, BRect r, LayerData *d, int8 *pat) {}
void DisplayDriver::StrokeLineArray(BPoint *pts, int32 numlines, RGBColor *colors, LayerData *d) {}
void DisplayDriver::SetMode(int32 mode) {}

View File

@ -0,0 +1,131 @@
#ifndef _DISPLAY_DRIVER_H_
#define _DISPLAY_DRIVER_H_
#include <GraphicsCard.h>
#include <SupportDefs.h>
#include <OS.h>
#include <Font.h>
#include <Rect.h>
#include "RGBColor.h"
class ServerCursor;
class ServerBitmap;
class LayerData;
#ifndef ROUND
#define ROUND(a) ( (a-long(a))>=.5)?(long(a)+1):(long(a))
#endif
typedef struct
{
uchar *xormask, *andmask;
int32 width, height;
int32 hotx, hoty;
} cursor_data;
#ifndef HOOK_DEFINE_CURSOR
#define HOOK_DEFINE_CURSOR 0
#define HOOK_MOVE_CURSOR 1
#define HOOK_SHOW_CURSOR 2
#define HOOK_DRAW_LINE_8BIT 3
#define HOOK_DRAW_LINE_16BIT 12
#define HOOK_DRAW_LINE_32BIT 4
#define HOOK_DRAW_RECT_8BIT 5
#define HOOK_DRAW_RECT_16BIT 13
#define HOOK_DRAW_RECT_32BIT 6
#define HOOK_BLIT 7
#define HOOK_DRAW_ARRAY_8BIT 8
#define HOOK_DRAW_ARRAY_16BIT 14 // Not implemented in current R5 drivers
#define HOOK_DRAW_ARRAY_32BIT 9
#define HOOK_SYNC 10
#define HOOK_INVERT_RECT 11
#endif
#define DRAW_COPY 0
#define DRAW_OVER 1
#define DRAW_ERASE 2
#define DRAW_INVERT 3
#define DRAW_ADD 4
#define DRAW_SUBTRACT 5
#define DRAW_BLEND 6
#define DRAW_MIN 7
#define DRAW_MAX 8
#define DRAW_SELECT 9
#define DRAW_ALPHA 10
class DisplayDriver
{
public:
DisplayDriver(void);
virtual ~DisplayDriver(void);
virtual bool Initialize(void);
virtual void Shutdown(void);
virtual void CopyBits(BRect src, BRect dest);
virtual void DrawBitmap(ServerBitmap *bmp, BRect src, BRect dest);
virtual void DrawChar(char c, BPoint pt);
// virtual void DrawPicture(SPicture *pic, BPoint pt);
virtual void DrawString(const char *string, int32 length, BPoint pt, LayerData *d, escapement_delta *delta=NULL);
virtual void FillArc(BRect r, float angle, float span, LayerData *d, int8 *pat);
virtual void FillBezier(BPoint *pts, LayerData *d, int8 *pat);
virtual void FillEllipse(BRect r, LayerData *d, int8 *pat);
virtual void FillPolygon(BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, int8 *pat);
virtual void FillRect(BRect r, LayerData *d, int8 *pat);
virtual void FillRoundRect(BRect r, float xrad, float yrad, LayerData *d, int8 *pat);
// virtual void FillShape(SShape *sh, LayerData *d, int8 *pat);
virtual void FillTriangle(BPoint *pts, BRect r, LayerData *d, int8 *pat);
virtual void HideCursor(void);
virtual bool IsCursorHidden(void);
virtual void MoveCursorTo(float x, float y);
virtual void InvertRect(BRect r);
virtual void ShowCursor(void);
virtual void ObscureCursor(void);
virtual void SetCursor(ServerCursor *cursor);
virtual void StrokeArc(BRect r, float angle, float span, LayerData *d, int8 *pat);
virtual void StrokeBezier(BPoint *pts, LayerData *d, int8 *pat);
virtual void StrokeEllipse(BRect r, LayerData *d, int8 *pat);
virtual void StrokeLine(BPoint start, BPoint end, LayerData *d, int8 *pat);
virtual void StrokePolygon(BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, int8 *pat, bool is_closed=true);
virtual void StrokeRect(BRect r, LayerData *d, int8 *pat);
virtual void StrokeRoundRect(BRect r, float xrad, float yrad, LayerData *d, int8 *pat);
// virtual void StrokeShape(SShape *sh, LayerData *d, int8 *pat);
virtual void StrokeTriangle(BPoint *pts, BRect r, LayerData *d, int8 *pat);
virtual void StrokeLineArray(BPoint *pts, int32 numlines, RGBColor *colors, LayerData *d);
virtual void SetMode(int32 mode);
virtual bool DumpToFile(const char *path);
uint8 GetDepth(void);
uint16 GetHeight(void);
uint16 GetWidth(void);
int32 GetMode(void);
protected:
void Lock(void);
void Unlock(void);
void SetDepthInternal(uint8 d);
void SetHeightInternal(uint16 h);
void SetWidthInternal(uint16 w);
void SetModeInternal(int32 m);
void SetCursorHidden(bool state);
void SetCursorObscured(bool state);
bool IsCursorObscured(bool state);
bool CursorStateChanged(void);
private:
sem_id lock_sem;
uint8 buffer_depth;
uint16 buffer_width;
uint16 buffer_height;
int32 buffer_mode;
drawing_mode drawmode;
int32 is_cursor_hidden;
bool is_cursor_obscured, cursor_state_changed;
};
#endif

View File

@ -0,0 +1,182 @@
#include "FontFamily.h"
#include "ServerFont.h"
#include FT_CACHE_H
extern FTC_Manager ftmanager;
FontStyle::FontStyle(const char *filepath, FT_Face face)
{
name=new BString(face->style_name);
cachedface=new CachedFaceRec;
cachedface->file_path=filepath;
family=NULL;
instances=new BList(0);
has_bitmaps=(face->num_fixed_sizes>0)?true:false;
is_fixedwidth=(face->face_flags & FT_FACE_FLAG_FIXED_WIDTH)?true:false;
is_scalable=(face->face_flags & FT_FACE_FLAG_SCALABLE)?true:false;
has_kerning=(face->face_flags & FT_FACE_FLAG_KERNING)?true:false;
glyphcount=face->num_glyphs;
charmapcount=face->num_charmaps;
}
FontStyle::~FontStyle(void)
{
delete name;
delete cachedface;
// Mark all instances as Free here
int32 index=0;
ServerFont *fs=(ServerFont*)instances->ItemAt(index);
while(fs)
{
fs->fstyle=NULL;
index++;
fs=(ServerFont*)instances->ItemAt(index);
}
instances->MakeEmpty();
delete instances;
}
const char *FontStyle::Style(void)
{
return name->String();
}
FT_Face FontStyle::GetFace(void)
{
FT_Face f;
return (FTC_Manager_Lookup_Face(ftmanager,cachedface,&f)!=0)?f:NULL;
}
int16 FontStyle::ConvertToUnicode(uint16 c)
{
FT_Face f;
if(FTC_Manager_Lookup_Face(ftmanager,cachedface,&f)!=0)
return 0;
return FT_Get_Char_Index(f,c);
}
ServerFont *FontStyle::Instantiate(float size, float rotation=0.0, float shear=90.0)
{
ServerFont *f=new ServerFont(this, size, rotation, shear);
instances->AddItem(f);
return f;
}
FontFamily::FontFamily(const char *namestr)
{
name=new BString(namestr);
styles=new BList(0);
}
FontFamily::~FontFamily(void)
{
delete name;
BString *string;
for(int32 i=0; i<styles->CountItems(); i++)
{
string=(BString *)styles->RemoveItem(i);
if(string)
delete string;
}
styles->MakeEmpty(); // should be empty, but just in case...
delete styles;
}
const char *FontFamily::GetName(void)
{
return name->String();
}
void FontFamily::AddStyle(const char *path,FT_Face face)
{
if(!path)
return;
BString style(face->style_name);
FontStyle *item;
// Don't add if it already is in the family.
int32 count=styles->CountItems();
for(int32 i=0; i<count; i++)
{
item=(FontStyle *)styles->ItemAt(i);
if(item->name->Compare(face->style_name)==0)
return;
}
item=new FontStyle(path, face);
item->family=this;
styles->AddItem(item);
AddDependent();
}
void FontFamily::RemoveStyle(const char *style)
{
int32 count=styles->CountItems();
if(!style || count<1)
return;
FontStyle *fs;
for(int32 i=0; i<count; i++)
{
fs=(FontStyle *)styles->ItemAt(i);
if(fs && fs->name->Compare(style)==0)
{
fs=(FontStyle *)styles->RemoveItem(i);
if(fs)
{
delete fs;
RemoveDependent();
}
}
}
}
int32 FontFamily::CountStyles(void)
{
return styles->CountItems();
}
bool FontFamily::HasStyle(const char *style)
{
int32 count=styles->CountItems();
if(!style || count<1)
return false;
FontStyle *fs;
for(int32 i=0; i<count; i++)
{
fs=(FontStyle *)styles->ItemAt(i);
if(fs && fs->name->Compare(style)==0)
return true;
}
return false;
}
const char *FontFamily::GetStyle(int32 index)
{
FontStyle *fs=(FontStyle*)styles->ItemAt(index);
if(!fs)
return NULL;
return fs->Style();
}
FontStyle *FontFamily::GetStyle(const char *style)
{
int32 count=styles->CountItems();
if(!style || count<1)
return NULL;
FontStyle *fs;
for(int32 i=0; i<count; i++)
{
fs=(FontStyle *)styles->ItemAt(i);
if(fs && fs->name->Compare(style)==0)
return fs;
}
return NULL;
}

View File

@ -0,0 +1,81 @@
#ifndef FONT_FAMILY_H_
#define FONT_FAMILY_H_
#include <String.h>
#include <Font.h>
#include <List.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include "SharedObject.h"
class FontFamily;
class ServerFont;
enum font_format
{
FONT_TRUETYPE=0,
FONT_TYPE_1,
FONT_OPENTYPE,
FONT_BDF,
FONT_CFF,
FONT_CID,
FONT_PCF,
FONT_PFR,
FONT_SFNT,
FONT_TYPE_42,
FONT_WINFONT,
};
// data structure used by the FreeType cache manager
typedef struct CachedFaceRec_
{
BString file_path;
int face_index;
} CachedFaceRec, *CachedFace;
class FontStyle : public SharedObject
{
public:
FontStyle(const char *filepath, FT_Face face);
~FontStyle(void);
ServerFont *Instantiate(float size, float rotation=0.0, float shear=90.0);
bool IsFixedWidth(void) { return is_fixedwidth; }
bool IsScalable(void) { return is_scalable; }
bool HasKerning(void) { return has_kerning; }
bool HasTuned(void) { return has_bitmaps; }
uint16 GlyphCount(void) { return glyphcount; }
uint16 CharMapCount(void) { return charmapcount; }
const char *Style(void);
FontFamily *Family(void) { return family; }
FT_Face GetFace(void);
int16 ConvertToUnicode(uint16 c);
protected:
friend FontFamily;
FontFamily *family;
uint16 glyphcount, charmapcount;
BString *name, *path;
BList *instances;
bool is_fixedwidth, is_scalable, has_kerning, has_bitmaps;
CachedFace cachedface;
uint8 format;
};
class FontFamily : public SharedObject
{
public:
FontFamily(const char *namestr);
~FontFamily(void);
const char *GetName(void);
void AddStyle(const char *path, FT_Face face);
void RemoveStyle(const char *style);
bool HasStyle(const char *style);
int32 CountStyles(void);
const char *GetStyle(int32 index);
FontStyle *GetStyle(const char *style);
protected:
BString *name;
BList *styles;
};
#endif

View File

@ -0,0 +1,53 @@
#ifndef FONTINSTANCE_H_
#define FONTINSTANCE_H_
class FontStyle;
#include <Font.h>
class FontInstance
{
public:
FontInstance(void);
FontInstance(float size, float rotation, float shear);
~FontInstance(void);
void SetProperties(float size=12.0, float rotation=0.0, float shear=90.0);
void SetSpacing(uint8 spacing);
void SetFlags(int32 flags);
void SetFace(int32 face);
void SetSize(float size);
void SetRotation(float rotation);
void SetShear(float shear);
void SetEncoding(uint8 encoding);
unicode_block Blocks(void);
BRect BoundingBox(void);
float Rotation(void) { return fRotation; }
float Shear(void) { return fShear; }
float Size(void) { return fSize; }
uint8 Spacing(void) { return fSpacing; }
uint8 Encoding(void) { return fEncoding; }
font_direction Direction(void) { return fDirection; }
FontStyle *Style(void) { return fStyle; }
void Height(font_height *height) { *height=fHeight; }
float fSize,
fRotation,
fShear;
int32 fToken,
fFlags,
fFace;
uint8 fEncoding,
fSpacing;
font_height fHeight;
font_direction fDirection;
FontStyle *fStyle;
};
#endif

View File

@ -0,0 +1,52 @@
#ifndef FONTSERVER_H_
#define FONTSERVER_H_
#include <OS.h>
#include <List.h>
#include <SupportDefs.h>
#include <Font.h>
#include <freetype.h>
#include <ftcache.h>
class FontFamily;
class FontStyle;
class ServerFont;
class FontServer
{
public:
FontServer(void);
~FontServer(void);
void Lock(void);
void Unlock(void);
bool IsInitialized(void) { return init; }
int32 CountFamilies(void);
int32 CountStyles(const char *family);
void RemoveFamily(const char *family);
status_t ScanDirectory(const char *path);
void SaveList(void);
FontStyle *GetStyle(font_family family, font_style face);
ServerFont *GetSystemPlain(void);
ServerFont *GetSystemBold(void);
ServerFont *GetSystemFixed(void);
bool SetSystemPlain(const char *family, const char *style, float size);
bool SetSystemBold(const char *family, const char *style, float size);
bool SetSystemFixed(const char *family, const char *style, float size);
bool FontsNeedUpdated(void) { return need_update; }
void FontsUpdated(void) { need_update=false; }
// FontInstance *GetInstance(font_family family, font_style face, int16 size, int16 rotation, int16 shear);
FontFamily *_FindFamily(const char *name);
FT_CharMap _GetSupportedCharmap(const FT_Face &face);
bool init;
sem_id lock;
BList *families;
ServerFont *plain, *bold, *fixed;
bool need_update;
};
extern FTC_Manager ftmanager;
extern FT_Library ftlib;
extern FontServer *fontserver;
#endif

View File

@ -0,0 +1,7 @@
#ifndef _SERVER_GLOBALS_H_
#define _SERVER_GLOBALS_H_
#include <List.h>
BList *gBitmaplist, *gLayerlist;
#endif

View File

@ -0,0 +1,39 @@
SubDir OBOS_TOP src servers app proto7 ;
UseFreeTypeHeaders ;
Server OBAppServer :
# Misc. Sources
BeDecorator.cpp
ColorUtils.cc
DebugTools.cpp
Decorator.cpp
PortLink.cpp
SystemPalette.cpp
RGBColor.cpp
# Operating Classes
AppServer.cpp
Desktop.cpp
Layer.cpp
ServerApp.cpp
ServerBitmap.cpp
ServerCursor.cpp
ServerWindow.cpp
WindowBorder.cpp
# Font Classes
FontFamily.cpp
FontServer.cpp
ServerFont.cpp
# Display Modules
DisplayDriver.cpp
LineCalc.cpp
ScreenDriver.cpp
ViewDriver.cpp
;
LinkSharedOSLibs OBAppServer : be root game translation stdc++.r4 freetype ;
SubInclude OBOS_TOP src servers app proto7 testobapp ;

View File

@ -0,0 +1,959 @@
/*
Layer.cpp
Class used for rendering to the frame buffer. One layer per view on screen and
also for window decorators
*/
#include "Layer.h"
#include "ServerWindow.h"
#include "Desktop.h"
#include "PortLink.h"
#include "DisplayDriver.h"
#include <iostream.h>
#include <Debug.h>
#include <string.h>
#include <stdio.h>
#include <OS.h>
//#define DEBUG_LAYERS
int64 solidhigh64=0xFFFFFFFFFFFFFFFFLL;
int64 solidlow64=0LL;
int64 mixedpat64=0xCCCCCCCCCCCCCCCCLL;
int8 *solidhigh=(int8*)&solidhigh64;
int8 *solidlow=(int8*)&solidlow64;
int8 *mixedpat=(int8*)&mixedpat64;
Layer::Layer(BRect rect, const char *layername, ServerWindow *srvwin,
int32 viewflags, int32 token)
{
if(rect.IsValid())
// frame is in parent layer's coordinates
frame=rect;
else
{
#ifdef DEBUG_LAYERS
printf("Invalid BRect: "); rect.PrintToStream();
#endif
frame.Set(0,0,1,1);
}
name=new BString(layername);
// Layer does not start out as a part of the tree
parent=NULL;
uppersibling=NULL;
lowersibling=NULL;
topchild=NULL;
bottomchild=NULL;
visible=new BRegion(Bounds());
full=new BRegion(Bounds());
invalid=NULL;
serverwin=srvwin;
view_token=token;
flags=viewflags;
hidecount=0;
is_dirty=false;
is_updating=false;
level=0;
layerdata=new LayerData;
#ifdef DEBUG_LAYERS
PrintToStream();
#endif
}
Layer::Layer(BRect rect, const char *layername)
{
// This constructor is used for the top layer in each workspace
if(rect.IsValid())
frame=rect;
else
frame.Set(0,0,1,1);
name=new BString(layername);
// Layer is the root for the workspace
parent=NULL;
uppersibling=NULL;
lowersibling=NULL;
topchild=NULL;
bottomchild=NULL;
visible=new BRegion(Bounds());
full=new BRegion(Bounds());
invalid=NULL;
serverwin=NULL;
flags=0;
hidecount=0;
is_dirty=false;
level=0;
view_token=-1;
layerdata=new LayerData;
#ifdef DEBUG_LAYERS
PrintToStream();
#endif
}
Layer::~Layer(void)
{
#ifdef DEBUG_LAYERS
printf("Layer Destructor for %s\n",name->String());
#endif
if(visible)
{
delete visible;
visible=NULL;
}
if(full)
{
delete full;
full=NULL;
}
if(invalid)
{
delete invalid;
invalid=NULL;
}
if(name)
{
delete name;
name=NULL;
}
if(layerdata)
{
delete layerdata;
layerdata=NULL;
}
}
// Tested for adding children with 1 and 2 child cases, but not more
void Layer::AddChild(Layer *layer)
{
// Adds a layer to the top of the layer's children
#ifdef DEBUG_LAYERS
printf("AddChild %s\n",layer->name->String());
printf("Before AddChild: \n");
PrintNode();
if(parent)
parent->PrintNode();
if(uppersibling)
uppersibling->PrintNode();
if(lowersibling)
lowersibling->PrintNode();
if(topchild)
topchild->PrintNode();
if(bottomchild)
bottomchild->PrintNode();
#endif
if(layer->parent!=NULL)
{
printf("ERROR: AddChild(): View already has a parent\n");
return;
}
layer->parent=this;
if(layer->visible && layer->hidecount==0 && visible)
{
// Technically, we could safely take the address of ConvertToParent(BRegion)
// but we don't just to avoid a compiler nag
BRegion *reg=new BRegion(layer->ConvertToParent(layer->visible));
visible->Exclude(reg);
delete reg;
}
// we need to change this to a loop for each lowersibling of the layer
if(topchild!=NULL)
{
// we're adding to the back side of the stack??
layer->lowersibling=topchild;
// added layer will be at the bottom of the stack
topchild->uppersibling=layer;
for(Layer *lay=layer->lowersibling; lay!=NULL; lay=lay->lowersibling)
{
if(layer->frame.Intersects(lay->frame))
{
if(lay->visible && lay->hidecount==0)
{
// reg is what is visible in the layer's parent's coordinate system
BRegion *reg=new BRegion(ConvertToParent(layer->visible));
// reg2 is the layer's visible region in the sibling's coordinate system
BRegion *reg2=new BRegion(lay->ConvertFromParent(reg));
delete reg;
// layer->lowersibling->visible->Exclude(reg2);
// lowersiblings occupy screen space _above_ a layer, so the layer itself
// must remove from its visible region
layer->visible->Exclude(reg2);
delete reg2;
}
}
}
}
else
bottomchild=layer;
topchild=layer;
layer->level=level+1;
#ifdef DEBUG_LAYERS
printf("After AddChild: \n");
PrintNode();
if(parent)
parent->PrintNode();
if(uppersibling)
uppersibling->PrintNode();
if(lowersibling)
lowersibling->PrintNode();
if(topchild)
topchild->PrintNode();
if(bottomchild)
bottomchild->PrintNode();
#endif
}
// Tested for cases with 1 and 2 children, but no more than that
void Layer::RemoveChild(Layer *layer)
{
// Remove a layer from the tree
#ifdef DEBUG_LAYERS
printf("RemoveChild %s\n",layer->name->String());
printf("Before RemoveChild: \n");
PrintNode();
if(parent)
parent->PrintNode();
if(uppersibling)
uppersibling->PrintNode();
if(lowersibling)
lowersibling->PrintNode();
if(topchild)
topchild->PrintNode();
if(bottomchild)
bottomchild->PrintNode();
#endif
if(layer->parent==NULL)
{
printf("ERROR: RemoveChild(): View doesn't have a parent\n");
return;
}
if(layer->parent!=this)
{
printf("ERROR: RemoveChild(): View is not a child of this layer\n");
return;
}
if(hidecount==0 && layer->visible && layer->parent->visible)
{
BRegion *reg=new BRegion(ConvertToParent(visible));
layer->parent->visible->Include(reg);
delete reg;
}
// Take care of parent
layer->parent=NULL;
if(topchild==layer)
topchild=layer->lowersibling;
if(bottomchild==layer)
bottomchild=layer->uppersibling;
// Take care of siblings
if(layer->uppersibling!=NULL)
layer->uppersibling->lowersibling=layer->lowersibling;
if(layer->lowersibling!=NULL)
layer->lowersibling->uppersibling=layer->uppersibling;
layer->SetLevel(0);
layer->uppersibling=NULL;
layer->lowersibling=NULL;
RebuildRegions();
#ifdef DEBUG_LAYERS
printf("After RemoveChild: \n");
PrintNode();
if(parent)
parent->PrintNode();
if(uppersibling)
uppersibling->PrintNode();
if(lowersibling)
lowersibling->PrintNode();
if(topchild)
topchild->PrintNode();
if(bottomchild)
bottomchild->PrintNode();
#endif
}
void Layer::RemoveSelf(void)
{
// A Layer removes itself from the tree (duh)
#ifdef DEBUG_LAYERS
printf("RemoveSelf %s\n",name->String());
#endif
if(parent==NULL)
{
printf("ERROR: RemoveSelf(): View doesn't have a parent\n");
return;
}
parent->RemoveChild(this);
}
Layer *Layer::GetChildAt(BPoint pt, bool recursive=false)
{
// Find out which child gets hit if we click at a certain spot. Returns NULL
// if there are no visible children or if the click does not hit a child layer
// If recursive==true, then it will continue to call until it reaches a layer
// which has no children, i.e. a layer that is at the top of its 'branch' in
// the layer tree
Layer *child;
if(recursive)
{
for(child=bottomchild; child!=NULL; child=child->uppersibling)
{
if(child->bottomchild!=NULL)
child->GetChildAt(pt,true);
if(child->hidecount>0)
continue;
if(child->frame.Contains(pt))
return child;
}
}
else
{
for(child=bottomchild; child!=NULL; child=child->uppersibling)
{
if(child->hidecount>0)
continue;
// if(child->visible && child->visible->Contains(ConvertFromTop(pt)))
// printf("child hit by mouse. News at 11\n");
if(child->frame.Contains(pt))
return child;
}
}
return NULL;
}
BRect Layer::Bounds(void)
{
return frame.OffsetToCopy(0,0);
}
BRect Layer::Frame(void)
{
return frame;
}
void Layer::SetLevel(int32 value)
{
// Sets hierarchy level of layer and all children
#ifdef DEBUG_LAYERS
printf("SetLevel %ld\n",value);
#endif
level=value;
Layer *lay;
lay=topchild;
while(lay!=NULL)
{
if(lay->topchild!=NULL)
lay->topchild->SetLevel(value+1);
lay=lay->lowersibling;
}
}
void Layer::PruneTree(void)
{
// recursively deletes all children (and grandchildren, etc) of the passed layer
// This is mostly used for server shutdown or deleting a workspace
#ifdef DEBUG_LAYERS
printf("PruneTree() at level %ld\n", level);
#endif
Layer *lay,*nextlay;
lay=topchild;
topchild=NULL;
while(lay!=NULL)
{
if(lay->topchild!=NULL)
{
// lay->topchild->PruneTree();
lay->PruneTree();
}
nextlay=lay->lowersibling;
lay->lowersibling=NULL;
delete lay;
lay=nextlay;
}
// Man, this thing is short. Elegant, ain't it? :P
}
Layer *Layer::FindLayer(int32 token)
{
// recursive search for a layer based on its view token
Layer *lay, *trylay;
// Search child layers first
for(lay=topchild; lay!=NULL; lay=lay->lowersibling)
{
if(lay->view_token==token)
return lay;
}
// Hmmm... not in this layer's children. Try lower descendants
for(lay=topchild; lay!=NULL; lay=lay->lowersibling)
{
trylay=lay->FindLayer(token);
if(trylay)
return trylay;
}
// Well, we got this far in the function, so apparently there is no match to be found
return NULL;
}
// Tested
void Layer::Invalidate(BRegion region)
{
int32 i;
BRect r;
// See if the region intersects with our current area
if(region.Intersects(Bounds()) && hidecount==0)
{
BRegion clippedreg(region);
clippedreg.IntersectWith(visible);
if(clippedreg.CountRects()>0)
{
is_dirty=true;
if(invalid)
invalid->Include(&clippedreg);
else
invalid=new BRegion(clippedreg);
}
}
BRegion *reg;
for(Layer *lay=topchild;lay!=NULL; lay=lay->lowersibling)
{
if(lay->hidecount==0)
{
reg=new BRegion(lay->ConvertFromParent(&region));
for(i=0;i<reg->CountRects();i++)
{
r=reg->RectAt(i);
if(frame.Intersects(r))
lay->Invalidate(r);
}
delete reg;
}
}
}
// Tested
void Layer::Invalidate(BRect rect)
{
// Make our own section dirty and pass it on to any children, if necessary....
// YES, WE ARE SHARING DIRT! Mudpies anyone? :D
#ifdef DEBUG_LAYERS
printf("Layer %s::Invalidate\n",name->String());
printf("Frame: ");frame.PrintToStream();
printf("Invalid rect: ");rect.PrintToStream();
printf("Visible: ");visible->PrintToStream();
printf("----------------\n");
#endif
if(Frame().Intersects(rect))
{
// Clip the rectangle to the visible region of the layer
if(visible->Intersects(rect))
{
BRegion reg(rect);
reg.IntersectWith(visible);
if(reg.CountRects()>0)
{
is_dirty=true;
if(invalid)
invalid->Include(&reg);
else
invalid=new BRegion(reg);
}
}
}
for(Layer *lay=topchild;lay!=NULL; lay=lay->lowersibling)
lay->Invalidate(lay->ConvertFromParent(rect));
}
void Layer::RequestDraw(void)
{
if(visible==NULL || hidecount>0)
return;
if(serverwin)
{
if(invalid==NULL)
invalid=new BRegion(*visible);
serverwin->RequestDraw(invalid->Frame());
delete invalid;
invalid=NULL;
}
is_dirty=false;
for(Layer *lay=topchild; lay!=NULL; lay=lay->lowersibling)
{
if(lay->IsDirty())
lay->RequestDraw();
}
}
bool Layer::IsDirty(void) const
{
// return is_dirty;
return (!invalid)?true:false;
}
void Layer::ShowLayer(void)
{
if(hidecount==0)
return;
hidecount--;
if(hidecount==0)
{
BRegion *reg=new BRegion(ConvertToParent(visible));
parent->visible->Exclude(reg);
delete reg;
is_dirty=true;
}
Layer *child;
for(child=topchild; child!=NULL; child=child->lowersibling)
child->ShowLayer();
}
void Layer::HideLayer(void)
{
if(hidecount==0)
{
BRegion *reg=new BRegion(ConvertToParent(visible));
parent->visible->Include(reg);
delete reg;
parent->is_dirty=true;
is_dirty=true;
}
hidecount++;
Layer *child;
for(child=topchild; child!=NULL; child=child->lowersibling)
child->HideLayer();
}
// Tested
uint32 Layer::CountChildren(void)
{
uint32 i=0;
Layer *lay=topchild;
while(lay!=NULL)
{
lay=lay->lowersibling;
i++;
}
return i;
}
void Layer::MoveBy(float x, float y)
{
BRect oldframe(frame);
frame.OffsetBy(x,y);
if(parent)
{
if(parent->invalid==NULL)
parent->invalid=new BRegion(oldframe);
else
parent->invalid->Include(oldframe);
}
// for(Layer *lay=topchild; lay!=NULL; lay=lay->lowersibling)
// lay->MoveBy(x,y);
// Invalidate(Frame());
}
void Layer::ResizeBy(float x, float y)
{
BRect oldframe=frame;
frame.right+=x;
frame.bottom+=y;
if(parent)
parent->RebuildRegions();
else
RebuildRegions();
// for(Layer *lay=topchild; lay!=NULL; lay=lay->lowersibling)
// lay->ResizeBy(x,y);
if(x<0 || y<0)
parent->Invalidate(oldframe);
// Invalidate(Frame());
}
void Layer::RebuildRegions(bool include_children=true)
{
BRegion *reg,*reg2;
if(full)
full->Include(Bounds());
else
full=new BRegion(Bounds());
if(visible)
visible->Include(Bounds());
else
visible=new BRegion(Bounds());
// Remove child footprints from visible region
for(Layer *childlay=topchild; childlay!=NULL; childlay=childlay->lowersibling)
{
if(childlay->visible && childlay->hidecount==0)
{
// reg is what is visible in the layer's parent's coordinate system
reg=new BRegion(ConvertToParent(visible));
// reg2 is the layer's visible region in the sibling's coordinate system
reg2=new BRegion(childlay->ConvertFromParent(reg));
delete reg;
// lowersiblings occupy screen space _above_ a layer, so the layer itself
// must remove from its visible region
visible->Exclude(reg2);
delete reg2;
}
}
// Remove lowersibling footprints, which are on top of the layer on screen
for(Layer *siblay=lowersibling; siblay!=NULL; siblay=siblay->lowersibling)
{
if(frame.Intersects(siblay->frame))
{
if(siblay->visible && siblay->hidecount==0)
{
// reg is what is visible in the layer's parent's coordinate system
reg=new BRegion(ConvertToParent(visible));
// reg2 is the layer's visible region in the sibling's coordinate system
reg2=new BRegion(siblay->ConvertFromParent(reg));
delete reg;
// lowersiblings occupy screen space _above_ a layer, so the layer itself
// must remove from its visible region
visible->Exclude(reg2);
delete reg2;
}
}
}
if(include_children)
{
for(Layer *lay=topchild; lay!=NULL; lay=lay->lowersibling)
{
if(lay->topchild)
lay->RebuildRegions(true);
}
}
}
void Layer::PrintToStream(void)
{
printf("-----------\nLayer %s\n",name->String());
if(parent)
printf("Parent: %s (%p)\n",parent->name->String(), parent);
else
printf("Parent: NULL\n");
if(uppersibling)
printf("Upper sibling: %s (%p)\n",uppersibling->name->String(), uppersibling);
else
printf("Upper sibling: NULL\n");
if(lowersibling)
printf("Lower sibling: %s (%p)\n",lowersibling->name->String(), lowersibling);
else
printf("Lower sibling: NULL\n");
if(topchild)
printf("Top child: %s (%p)\n",topchild->name->String(), topchild);
else
printf("Top child: NULL\n");
if(bottomchild)
printf("Bottom child: %s (%p)\n",bottomchild->name->String(), bottomchild);
else
printf("Bottom child: NULL\n");
printf("Frame: "); frame.PrintToStream();
printf("Token: %ld\nLevel: %ld\n",view_token, level);
printf("Hide count: %u\n",hidecount);
if(invalid)
{
printf("Invalid Areas: "); invalid->PrintToStream();
}
else
printf("Invalid Areas: NULL\n");
if(visible)
{
printf("Visible Areas: "); visible->PrintToStream();
}
else
printf("Visible Areas: NULL\n");
printf("Is updating = %s\n",(is_updating)?"yes":"no");
}
void Layer::PrintNode(void)
{
printf("-----------\nLayer %s\n",name->String());
if(parent)
printf("Parent: %s (%p)\n",parent->name->String(), parent);
else
printf("Parent: NULL\n");
if(uppersibling)
printf("Upper sibling: %s (%p)\n",uppersibling->name->String(), uppersibling);
else
printf("Upper sibling: NULL\n");
if(lowersibling)
printf("Lower sibling: %s (%p)\n",lowersibling->name->String(), lowersibling);
else
printf("Lower sibling: NULL\n");
if(topchild)
printf("Top child: %s (%p)\n",topchild->name->String(), topchild);
else
printf("Top child: NULL\n");
if(bottomchild)
printf("Bottom child: %s (%p)\n",bottomchild->name->String(), bottomchild);
else
printf("Bottom child: NULL\n");
if(visible)
{
printf("Visible Areas: "); visible->PrintToStream();
}
else
printf("Visible Areas: NULL\n");
}
// Tested
BRect Layer::ConvertToParent(BRect rect)
{
return (rect.OffsetByCopy(frame.LeftTop()));
}
// Tested
BPoint Layer::ConvertToParent(BPoint point)
{
float x=point.x + frame.left,
y=point.y+frame.top;
return (BPoint(x,y));
}
// Tested
BRegion Layer::ConvertToParent(BRegion *reg)
{
BRegion newreg;
for(int32 i=0; i<reg->CountRects();i++)
newreg.Include(ConvertToParent(reg->RectAt(i)));
return BRegion(newreg);
}
// Tested
BRect Layer::ConvertFromParent(BRect rect)
{
return (rect.OffsetByCopy(frame.left*-1,frame.top*-1));
}
// Tested
BPoint Layer::ConvertFromParent(BPoint point)
{
return ( point-frame.LeftTop());
}
// Tested
BRegion Layer::ConvertFromParent(BRegion *reg)
{
BRegion newreg;
for(int32 i=0; i<reg->CountRects();i++)
newreg.Include(ConvertFromParent(reg->RectAt(i)));
return BRegion(newreg);
}
// Tested
BRegion Layer::ConvertToTop(BRegion *reg)
{
BRegion newreg;
for(int32 i=0; i<reg->CountRects();i++)
newreg.Include(ConvertToTop(reg->RectAt(i)));
return BRegion(newreg);
}
// Tested
BRect Layer::ConvertToTop(BRect rect)
{
if (parent!=NULL)
return(parent->ConvertToTop(rect.OffsetByCopy(frame.LeftTop())) );
else
return(rect);
}
// Tested
BPoint Layer::ConvertToTop(BPoint point)
{
if (parent!=NULL)
return(parent->ConvertToTop(point + frame.LeftTop()) );
else
return(point);
}
// Tested
BRegion Layer::ConvertFromTop(BRegion *reg)
{
BRegion newreg;
for(int32 i=0; i<reg->CountRects();i++)
newreg.Include(ConvertFromTop(reg->RectAt(i)));
return BRegion(newreg);
}
// Tested
BRect Layer::ConvertFromTop(BRect rect)
{
if (parent!=NULL)
return(parent->ConvertFromTop(rect.OffsetByCopy(frame.LeftTop().x*-1,
frame.LeftTop().y*-1)) );
else
return(rect);
}
// Tested
BPoint Layer::ConvertFromTop(BPoint point)
{
if (parent!=NULL)
return(parent->ConvertFromTop(point - frame.LeftTop()) );
else
return(point);
}
RootLayer::RootLayer(BRect rect, const char *layername, ServerWindow *srvwin,
int32 viewflags, int32 token)
: Layer(rect,layername,srvwin,viewflags,token)
{
updater_id=-1;
}
RootLayer::RootLayer(BRect rect, const char *layername)
: Layer(rect,layername)
{
updater_id=-1;
driver=get_gfxdriver();
}
RootLayer::~RootLayer(void)
{
}
void RootLayer::SetVisible(bool fVisible)
{
if(is_visible!=fVisible)
{
is_visible=fVisible;
/* if(visible)
{
updater_id=spawn_thread(UpdaterThread,name->String(),B_NORMAL_PRIORITY,this);
if(updater_id!=B_NO_MORE_THREADS && updater_id!=B_NO_MEMORY)
resume_thread(updater_id);
}
*/
}
}
bool RootLayer::IsVisible(void) const
{
return is_visible;
}
int32 RootLayer::UpdaterThread(void *data)
{
// Updater thread which checks to see if its layer needs updating. If so, then
// call the recursive function RequestDraw.
RootLayer *root=(RootLayer*)data;
while(1)
{
if(!root->is_visible)
{
return 0;
exit_thread(1);
}
if(root->IsDirty())
{
layerlock->Lock();
root->RequestDraw();
layerlock->Unlock();
}
}
}
void RootLayer::RequestDraw(void)
{
if(!invalid)
return;
ASSERT(driver!=NULL);
#ifdef DEBUG_LAYERS
printf("Root::RequestDraw: invalid rects: %ld\n",invalid->CountRects());
#endif
// Redraw the base
for(int32 i=0; invalid->CountRects();i++)
{
if(invalid->RectAt(i).IsValid())
{
#ifdef DEBUG_LAYERS
printf("Root::RequestDraw:FillRect, color ",layerdata->lowcolor.PrintToStream());
#endif
driver->FillRect(invalid->RectAt(i),layerdata, solidlow);
}
else
break;
}
delete invalid;
invalid=NULL;
is_dirty=false;
// force redraw of all dirty windows
for(Layer *lay=topchild; lay!=NULL; lay=lay->lowersibling)
{
if(lay->IsDirty())
lay->RequestDraw();
}
}
void RootLayer::SetColor(RGBColor col)
{
layerdata->lowcolor=col;
#ifdef DEBUG_LAYERS
printf("Root::SetColor - ",col.PrintToStream());
#endif
}
RGBColor RootLayer::GetColor(void) const
{
return layerdata->lowcolor;
}

View File

@ -0,0 +1,110 @@
#ifndef _LAYER_H_
#define _LAYER_H_
#include <GraphicsDefs.h>
#include <Rect.h>
#include <Region.h>
#include <List.h>
#include <String.h>
#include <OS.h>
#include "LayerData.h"
class ServerWindow;
class UpdateNode;
class DisplayDriver;
class Layer
{
public:
Layer(BRect rect, const char *layername, ServerWindow *srvwin,
int32 viewflags, int32 token);
Layer(BRect rect, const char *layername);
virtual ~Layer(void);
void ShowLayer(void);
void HideLayer(void);
Layer *FindLayer(int32 token);
void MoveLayer(BPoint delta, bool include_children=true);
void AddChild(Layer *child);
void RemoveChild(Layer *child);
void RemoveSelf(void);
uint32 CountChildren(void);
Layer *GetChildAt(BPoint pt, bool recursive=false);
BRect Bounds(void);
BRect Frame(void);
void MoveBy(float x, float y);
void ResizeBy(float x, float y);
void RebuildRegions(bool include_children=true);
bool IsDirty(void) const;
void PrintToStream(void);
void PrintNode(void);
void PruneTree(void);
void SetLevel(int32 value);
void Invalidate(BRect rect);
void Invalidate(BRegion region);
virtual void RequestDraw(void);
BRect ConvertToParent(BRect rect);
BPoint ConvertToParent(BPoint point);
BRegion ConvertToParent(BRegion *reg);
BRect ConvertFromParent(BRect rect);
BPoint ConvertFromParent(BPoint point);
BRegion ConvertFromParent(BRegion *reg);
BRegion ConvertToTop(BRegion *reg);
BRect ConvertToTop(BRect rect);
BPoint ConvertToTop(BPoint point);
BRegion ConvertFromTop(BRegion *reg);
BRect ConvertFromTop(BRect rect);
BPoint ConvertFromTop(BPoint point);
BRect frame;
Layer *parent,
*uppersibling,
*lowersibling,
*topchild,
*bottomchild;
BRegion *visible,
*invalid,
*full;
ServerWindow *serverwin;
BString *name;
int32 view_token; // identifier for the corresponding view
int32 level; // how far layer is from root
int32 flags; // view flags
uint8 hidecount;
bool is_dirty; // true if we need to redraw
bool is_updating;
LayerData *layerdata;
};
class RootLayer : public Layer
{
public:
RootLayer(BRect rect, const char *layername, ServerWindow *srvwin,
int32 viewflags, int32 token);
RootLayer(BRect rect, const char *layername);
~RootLayer(void);
virtual void RequestDraw(void);
void SetVisible(bool is_visible);
bool IsVisible(void) const;
void SetColor(RGBColor col);
RGBColor GetColor(void) const;
static int32 UpdaterThread(void *data);
private:
thread_id updater_id;
bool is_visible;
DisplayDriver *driver;
};
extern BLocker *layerlock;
extern BList *layerlist;
extern Layer *rootlayer;
#endif

View File

@ -0,0 +1,50 @@
#ifndef LAYERDATA_H_
#define LAYERDATA_H_
#include <Point.h>
#include "RGBColor.h"
#include "ServerFont.h"
#include "FontServer.h"
class ServerBitmap;
class LayerData
{
public:
LayerData(void)
{
pensize=1.0;
penlocation.Set(0,0);
draw_mode=B_OP_COPY;
bitmap_background=NULL;
bitmap_overlay=NULL;
highcolor.SetColor(0,0,0,255);
lowcolor.SetColor(255,255,255,255);
font=fontserver->GetSystemPlain();
scale=1.0;
}
~LayerData(void)
{
if(font)
{
delete font;
font=NULL;
}
}
float pensize;
BPoint penlocation;
drawing_mode draw_mode;
ServerBitmap *bitmap_background;
ServerBitmap *bitmap_overlay;
RGBColor highcolor, lowcolor;
ServerFont *font;
float scale;
};
extern int8 *solidhigh;
extern int8 *solidlow;
extern int8 *mixedpat;
extern int64 solidhigh64;
extern int64 solidlow64;
extern int64 mixedpat64;
#endif

View File

@ -0,0 +1,20 @@
#include "LineCalc.h"
LineCalc::LineCalc(const BPoint &pta, const BPoint &ptb)
{
start=pta;
end=ptb;
slope=(start.y-end.y)/(start.x-end.x);
offset=start.y-(slope * start.x);
}
float LineCalc::GetX(float y)
{
return ( (y-offset)/slope );
}
float LineCalc::GetY(float x)
{
return ( (slope * x) + offset );
}

View File

@ -0,0 +1,20 @@
#ifndef LINECALC_H_
#define LINECALC_H_
#include <Point.h>
class LineCalc
{
public:
LineCalc(const BPoint &pta, const BPoint &ptb);
float GetX(float y);
float GetY(float x);
float Slope(void) { return slope; }
float Offset(void) { return offset; }
private:
float slope;
float offset;
BPoint start, end;
};
#endif

View File

@ -0,0 +1,438 @@
/*
PortLink.cpp:
A helper class for port-based messaging
------------------------------------------------------------------------
How it works:
The class utilizes a fixed-size array of PortLinkData object pointers. When
data is attached, a new PortLinkData object is allocated and a copy of the
passed data is created inside it. When the time comes for the message to be sent,
the data is pieced together into a flattened array and written to the port.
------------------------------------------------------------------------
Data members:
*attachments[] - fixed-size array of pointers used to hold the attached data
opcode - message value which is sent along with any data
target - port to which the message is sent when Flush() is called
replyport - port used with synchronous messaging - FlushWithReply()
bufferlength - total bytes taken up by attachments
num_attachments - internal variable which is used to track which "slot"
will be the next one to receive an attachment object
*/
#include "PortLink.h"
#include <string.h>
#include <stdio.h>
#include <malloc.h>
//#define PLDEBUG
// Internal data storage class for holding attached data whilst it is waiting
// to be Flattened() and then Flushed(). There is no need for this to be called outside
// the PortLink class.
class PortLinkData
{
public:
PortLinkData(void);
~PortLinkData(void);
bool Set(void *data, size_t size);
char *buffer;
size_t buffersize;
};
PortLink::PortLink(port_id port)
{
// For this class to be useful (and to prevent a lot of init problems)
// we require a port in the constructor
target=port;
// We start out without any data attached to the port message
num_attachments=0;
opcode=0;
bufferlength=0;
replyport=create_port(30,"PortLink reply port");
}
PortLink::~PortLink(void)
{
// If, for some odd reason, this is deleted with something attached,
// free the memory used by the attachments. We do not flush the queue
// because the port may no longer be valid in cases such as the app
// is in the process of quitting
MakeEmpty();
}
void PortLink::SetOpCode(int32 code)
{
// Sets the message code. This does not change once the message is sent.
// Another call to SetOpCode() is required for such things.
opcode=code;
}
void PortLink::SetPort(port_id port)
{
// Sets the target port. While not necessary in most uses, this exists
// mostly to prevent flexibility problems
target=port;
}
port_id PortLink::GetPort(void)
{
// Simply returns the port at which the object is pointed.
return target;
}
void PortLink::Flush(bigtime_t timeout=B_INFINITE_TIMEOUT)
{
// Fires a message off to the target, complete with attachments. NOTE:
// the recipient must delete all attachments, being the PortLink object assumes
// no responsiblity for the attachments once the message is sent.
int8 *msgbuffer;
int32 size;
if(num_attachments>0)
{
FlattenData(&msgbuffer,&size);
// Dump message to port, reset attachments, and clean up
if(timeout!=B_INFINITE_TIMEOUT)
write_port_etc(target,opcode,msgbuffer,size,B_TIMEOUT, timeout);
else
write_port(target,opcode,msgbuffer,size);
MakeEmpty();
}
else
{
if(timeout!=B_INFINITE_TIMEOUT)
write_port_etc(target,opcode,NULL,0,B_TIMEOUT, timeout);
else
write_port(target,opcode,NULL,0);
}
}
int8* PortLink::FlushWithReply(int32 *code, status_t *status, ssize_t *buffersize, bigtime_t timeout=B_INFINITE_TIMEOUT)
{
// Fires a message to the target and then waits for a reply. The target will
// receive a message with the first item being the port_id to reply to.
// NOTE: like Flush(), any attached data must be deleted.
// Effectively, an Attach() call inlined for changes
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
{
*status=B_ERROR;
return NULL;
}
// create a new storage object and stash the data
PortLinkData *pld=new PortLinkData;
if(pld->Set(&replyport,sizeof(port_id)))
{
bufferlength+=sizeof(port_id);
}
else
{
delete pld;
*status=B_ERROR;
return NULL;
}
// Flatten() inlined to make some necessary changes
int8 *buffer=new int8[bufferlength];
int8 *bufferindex=buffer;
size_t size=0;
// attach our port_id first
memcpy(bufferindex, pld->buffer, pld->buffersize);
bufferindex += pld->buffersize;
size+=pld->buffersize;
// attach everything else
for(int i=0;i<num_attachments;i++)
{
pld=attachments[i];
memcpy(bufferindex, pld->buffer, pld->buffersize);
bufferindex += pld->buffersize;
size+=pld->buffersize;
}
// Flush the thing....FOOSH! :P
write_port(target,opcode,buffer,size);
MakeEmpty();
delete buffer;
// Now we wait for the reply
if(timeout==B_INFINITE_TIMEOUT)
{
*buffersize=port_buffer_size(replyport);
if(*buffersize>0)
buffer=(int8*)new int8[*buffersize];
read_port(replyport,code, buffer, *buffersize);
}
else
{
*buffersize=port_buffer_size_etc(replyport,0,timeout);
if(*buffersize==B_TIMED_OUT)
{
*status=*buffersize;
return NULL;
}
if(*buffersize>0)
buffer=(int8*)new int8[*buffersize];
read_port(replyport,code, buffer, *buffersize);
}
// We got this far, so we apparently have some data
*status=B_OK;
return buffer;
}
void PortLink::Attach(void *data, size_t size)
{
// This is the member called to attach data to a message. Attachments are
// treated to be in 'Append' mode, tacking on each attached piece of data
// to the end of the list.
// Prevent parameter problems
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
return;
if(size==0)
return;
// create a new storage object and stash the data
PortLinkData *pld=new PortLinkData;
if(pld->Set(data,size))
{
num_attachments++;
attachments[num_attachments-1]=pld;
bufferlength+=size;
}
else
{
delete pld;
}
}
// These functions were added for a major convenience in passing common types
// Eventually, I'd like to templatize these, but for now, this'll do
void PortLink::Attach(int32 data)
{
// Prevent parameter problems
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
return;
int32 size=sizeof(int32);
// create a new storage object and stash the data
PortLinkData *pld=new PortLinkData;
if(pld->Set(&data,size))
{
num_attachments++;
attachments[num_attachments-1]=pld;
bufferlength+=size;
}
else
{
delete pld;
}
}
void PortLink::Attach(int16 data)
{
// Prevent parameter problems
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
return;
int32 size=sizeof(int16);
// create a new storage object and stash the data
PortLinkData *pld=new PortLinkData;
if(pld->Set(&data,size))
{
num_attachments++;
attachments[num_attachments-1]=pld;
bufferlength+=size;
}
else
{
delete pld;
}
}
void PortLink::Attach(int8 data)
{
// Prevent parameter problems
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
return;
int32 size=sizeof(int8);
// create a new storage object and stash the data
PortLinkData *pld=new PortLinkData;
if(pld->Set(&data,size))
{
num_attachments++;
attachments[num_attachments-1]=pld;
bufferlength+=size;
}
else
{
delete pld;
}
}
void PortLink::Attach(float data)
{
// Prevent parameter problems
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
return;
int32 size=sizeof(float);
// create a new storage object and stash the data
PortLinkData *pld=new PortLinkData;
if(pld->Set(&data,size))
{
num_attachments++;
attachments[num_attachments-1]=pld;
bufferlength+=size;
}
else
{
delete pld;
}
}
void PortLink::Attach(bool data)
{
// Prevent parameter problems
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
return;
int32 size=sizeof(bool);
// create a new storage object and stash the data
PortLinkData *pld=new PortLinkData;
if(pld->Set(&data,size))
{
num_attachments++;
attachments[num_attachments-1]=pld;
bufferlength+=size;
}
else
{
delete pld;
}
}
void PortLink::Attach(BRect data)
{
// Prevent parameter problems
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
return;
int32 size=sizeof(BRect);
// create a new storage object and stash the data
PortLinkData *pld=new PortLinkData;
if(pld->Set(&data,size))
{
num_attachments++;
attachments[num_attachments-1]=pld;
bufferlength+=size;
}
else
{
delete pld;
}
}
void PortLink::Attach(BPoint data)
{
// Prevent parameter problems
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
return;
int32 size=sizeof(BPoint);
// create a new storage object and stash the data
PortLinkData *pld=new PortLinkData;
if(pld->Set(&data,size))
{
num_attachments++;
attachments[num_attachments-1]=pld;
bufferlength+=size;
}
else
{
delete pld;
}
}
void PortLink::FlattenData(int8 **buffer,int32 *size)
{
// This function is where all the magic happens, but it is strictly internal.
// It iterates through each PortLinkData object and copies it to the main buffer
// which ends up, ultimately, being written to the PortLink's target port.
// skip if there aree no attachments
if(bufferlength<1)
return;
*buffer=new int8[bufferlength];
int8 *bufferindex=*buffer;
PortLinkData *pld;
*size=0;
for(int i=0;i<num_attachments;i++)
{
pld=attachments[i];
memcpy(bufferindex, pld->buffer, pld->buffersize);
bufferindex += pld->buffersize;
*size+=pld->buffersize;
}
}
void PortLink::MakeEmpty(void)
{
// Nukes all the attachments currently held by the PortLink class
if(num_attachments!=0)
{
for(int i=0; i<num_attachments; i++)
{
delete attachments[i];
}
}
num_attachments=0;
bufferlength=0;
}
PortLinkData::PortLinkData(void)
{
// Initialize object to empty
buffersize=0;
}
PortLinkData::~PortLinkData(void)
{
// Frees the buffer if we actually used the class to store data
if(buffersize>0)
free(buffer);
}
bool PortLinkData::Set(void *data, size_t size)
{
// Function copies the passed to the internal buffers for storage
if(size>0 && buffersize==0 && data!=NULL)
{
buffer=(char *)malloc(size);
if(buffer==NULL)
return false;
memcpy(buffer, data, size);
buffersize=size;
return true;
}
return false;
}

View File

@ -0,0 +1,43 @@
#ifndef _PORTLINK_H_
#define _PORTLINK_H_
#include <Errors.h>
#include <OS.h>
#include <SupportDefs.h>
#include <Rect.h>
#ifndef _PORTLINK_BUFFERSIZE
#define _PORTLINK_MAX_ATTACHMENTS 50
#endif
class PortLinkData;
class PortLink
{
public:
PortLink(port_id port);
~PortLink(void);
void SetOpCode(int32 code);
void SetPort(port_id port);
port_id GetPort(void);
void Flush(bigtime_t timeout=B_INFINITE_TIMEOUT);
int8* FlushWithReply(int32 *code, status_t *status, ssize_t *buffersize,
bigtime_t timeout=B_INFINITE_TIMEOUT);
void Attach(void *data, size_t size);
void Attach(int32 data);
void Attach(int16 data);
void Attach(int8 data);
void Attach(float data);
void Attach(bool data);
void Attach(BRect data);
void Attach(BPoint data);
void MakeEmpty(void);
protected:
void FlattenData(int8 **buffer,int32 *size);
port_id target, replyport;
int32 opcode, bufferlength;
int num_attachments;
PortLinkData *attachments[_PORTLINK_MAX_ATTACHMENTS];
};
#endif

View File

@ -0,0 +1,176 @@
/*
RGBColor.cpp
Color encapsulation class for app_server.
*/
#include <stdio.h>
#include "RGBColor.h"
RGBColor::RGBColor(uint8 r, uint8 g, uint8 b, uint8 a=255)
{
SetColor(r,g,b,a);
}
RGBColor::RGBColor(int r, int g, int b, int a=255)
{
SetColor(r,g,b,a);
}
RGBColor::RGBColor(rgb_color col)
{
SetColor(col);
}
RGBColor::RGBColor(uint16 col)
{
SetColor(col);
}
RGBColor::RGBColor(uint8 col)
{
SetColor(col);
}
RGBColor::RGBColor(const RGBColor &col)
{
color32=col.color32;
color16=col.color16;
color8=col.color8;
}
RGBColor::RGBColor(void)
{
SetColor(0,0,0,0);
}
uint8 RGBColor::GetColor8(void)
{
return color8;
}
uint16 RGBColor::GetColor16(void)
{
return color16;
}
rgb_color RGBColor::GetColor32(void)
{
return color32;
}
void RGBColor::SetColor(uint8 r, uint8 g, uint8 b, uint8 a=255)
{
color32.red=r;
color32.green=g;
color32.blue=b;
color32.alpha=a;
}
void RGBColor::SetColor(int r, int g, int b, int a=255)
{
color32.red=(uint8)r;
color32.green=(uint8)g;
color32.blue=(uint8)b;
color32.alpha=(uint8)a;
}
void RGBColor::SetColor(uint16 col16)
{
// Pared-down version from what is used in the app_server to
// eliminate some dependencies
color16=col16;
}
void RGBColor::SetColor(uint8 col8)
{
// Pared-down version from what is used in the app_server to
// eliminate some dependencies
color8=col8;
}
void RGBColor::SetColor(rgb_color color)
{
// Pared-down version from what is used in the app_server to
// eliminate some dependencies
color32=color;
}
void RGBColor::SetColor(const RGBColor &col)
{
color32=col.color32;
color16=col.color16;
color8=col.color8;
}
RGBColor & RGBColor::operator=(const RGBColor &col)
{
color32=col.color32;
color16=col.color16;
color8=col.color8;
return *this;
}
RGBColor & RGBColor::operator=(rgb_color col)
{
color32=col;
return *this;
}
RGBColor RGBColor::MakeBlendColor(RGBColor color, float position)
{
rgb_color col=color32;
rgb_color col2=color.color32;
rgb_color newcol={0,0,0,0};
float mod=0;
int16 delta;
if(position<0 || position>1)
return newcol;
delta=int16(col2.red)-int16(col.red);
mod=col.red + (position * delta);
newcol.red=uint8(mod);
if(mod>255 )
newcol.red=255;
if(mod<0 )
newcol.red=0;
delta=int16(col2.green)-int16(col.green);
mod=col.green + (position * delta);
newcol.green=uint8(mod);
if(mod>255 )
newcol.green=255;
if(mod<0 )
newcol.green=0;
delta=int16(col2.blue)-int16(col.blue);
mod=col.blue + (position * delta);
newcol.blue=uint8(mod);
if(mod>255 )
newcol.blue=255;
if(mod<0 )
newcol.blue=0;
delta=int8(col2.alpha)-int8(col.alpha);
mod=col.alpha + (position * delta);
newcol.alpha=uint8(mod);
if(mod>255 )
newcol.alpha=255;
if(mod<0 )
newcol.alpha=0;
#ifdef DEBUG_COLOR_UTILS
printf("MakeBlendColor( {%u,%u,%u,%u}, {%u,%u,%u,%u}, %f) : {%u,%u,%u,%u}\n",
col.red,col.green,col.blue,col.alpha,
col2.red,col2.green,col2.blue,col2.alpha,
position,
newcol.red,newcol.green,newcol.blue,newcol.alpha);
#endif
return RGBColor(newcol);
}
void RGBColor::PrintToStream(void)
{
printf("RGBColor (%u,%u,%u,%u)\n", color32.red,color32.green,color32.blue,color32.alpha);
}

View File

@ -0,0 +1,35 @@
#ifndef RGBCOLOR_H_
#define RGBCOLOR_H_
#include <GraphicsDefs.h>
class RGBColor
{
public:
RGBColor(uint8 r, uint8 g, uint8 b, uint8 a=255);
RGBColor(int r, int g, int b, int a=255);
RGBColor(rgb_color col);
RGBColor(uint16 col);
RGBColor(uint8 col);
RGBColor(const RGBColor &col);
RGBColor(void);
void PrintToStream(void);
uint8 GetColor8(void);
uint16 GetColor16(void);
rgb_color GetColor32(void);
void SetColor(uint8 r, uint8 g, uint8 b, uint8 a=255);
void SetColor(int r, int g, int b, int a=255);
void SetColor(uint16 color16);
void SetColor(uint8 color8);
void SetColor(rgb_color color);
void SetColor(const RGBColor &col);
RGBColor MakeBlendColor(RGBColor color, float position);
RGBColor & operator=(const RGBColor &col);
RGBColor & operator=(rgb_color col);
protected:
rgb_color color32;
uint16 color16;
uint8 color8;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,746 @@
/*
ServerApp.cpp
Class which works with a BApplication. Handles all messages coming
from and going to its application.
*/
//#define DEBUG_SERVERAPP_MSGS
//#define DEBUG_SERVERAPP_CURSORS
//#define DEBUG_SERVERAPP_MISC
#include <AppDefs.h>
#include <Cursor.h>
#include <List.h>
#include <String.h>
#include "Desktop.h"
#include "DisplayDriver.h"
//#include "Layer.h"
#include "FontServer.h"
#include "ServerApp.h"
#include "ServerWindow.h"
#include "ServerBitmap.h"
#include "ServerProtocol.h"
#include "ServerCursor.h"
#include "PortLink.h"
#include <stdio.h>
#include <iostream.h>
#include <string.h>
#include "DebugTools.h"
#include "LayerData.h"
ServerApp::ServerApp(port_id msgport, char *signature)
{
// need to copy the signature because the message buffer
// owns the copy which we are passed as a parameter.
app_sig=(signature)?signature:"Application";
// sender is the monitored app's event port
sender=msgport;
applink=new PortLink(sender);
port_info pinfo;
get_port_info(sender,&pinfo);
target_id=pinfo.team;
// receiver is the port to which the app sends messages for the server
receiver=create_port(30,app_sig.String());
#ifdef DEBUG_SERVERAPP_MISC
printf("ServerApp port for app %s is at %ld\n",app_sig.String(),receiver);
#endif
if(receiver==B_NO_MORE_PORTS)
{
// uh-oh. We have a serious problem. Tell the app to quit
applink->SetOpCode(B_QUIT_REQUESTED);
applink->Flush();
}
// No longer necessary. This message is sent from the app_server thread
// now because of changes in the application structure from previous
// prototypes.
/* else
{
// Everything checks out, so tell the application
// where to send future messages
applink->SetOpCode(SET_SERVER_PORT);
applink->Attach(&receiver,sizeof(port_id));
applink->Flush();
}
*/
applink->SetPort(sender);
winlist=new BList(0);
bmplist=new BList(0);
driver=get_gfxdriver();
isactive=false;
cursor=NULL;
// This exists for testing the graphics access module and will disappear
// when layers are implemented
high.red=255;
high.green=255;
high.blue=255;
high.alpha=255;
low.red=0;
low.green=0;
low.blue=0;
low.alpha=255;
}
ServerApp::~ServerApp(void)
{
#ifdef DEBUG_SERVERAPP_MISC
printf("%s: ~ServerApp\n",app_sig.String());
#endif
int32 i;
ServerWindow *tempwin;
for(i=0;i<winlist->CountItems();i++)
{
tempwin=(ServerWindow*)winlist->ItemAt(i);
if(tempwin)
delete tempwin;
}
winlist->MakeEmpty();
delete winlist;
ServerBitmap *tempbmp;
for(i=0;i<bmplist->CountItems();i++)
{
tempbmp=(ServerBitmap*)bmplist->ItemAt(i);
if(tempbmp)
delete tempbmp;
}
bmplist->MakeEmpty();
delete bmplist;
delete applink;
applink=NULL;
if(cursor)
delete cursor;
// Kill the monitor thread if it exists
thread_info info;
if(get_thread_info(monitor_thread,&info)==B_OK)
kill_thread(monitor_thread);
}
bool ServerApp::Run(void)
{
#ifdef DEBUG_SERVERAPP_MISC
printf("%s: Run()\n",app_sig.String());
#endif
// Unlike a BApplication, a ServerApp is *supposed* to return immediately
// when its Run function is called.
monitor_thread=spawn_thread(MonitorApp,app_sig.String(),B_NORMAL_PRIORITY,this);
if(monitor_thread==B_NO_MORE_THREADS || monitor_thread==B_NO_MEMORY)
return false;
resume_thread(monitor_thread);
return true;
}
bool ServerApp::PingTarget(void)
{
// This function is called by the app_server thread to ensure that
// the target app still exists. We do this not by sending a message
// but by calling get_port_info. We don't want to send ping messages
// just because the app might simply be hung. If this is the case, it
// should be up to the user to kill it. If the app has been killed, its
// ports will be invalid. Thus, if get_port_info returns an error, we
// tell the app_server to delete the respective ServerApp.
team_info tinfo;
if(get_team_info(target_id,&tinfo)==B_BAD_TEAM_ID)
{
port_id serverport=find_port(SERVER_PORT_NAME);
if(serverport==B_NAME_NOT_FOUND)
{
printf("PANIC: ServerApp %s could not find the app_server port in PingTarget()!\n",app_sig.String());
return false;
}
applink->SetPort(serverport);
applink->SetOpCode(DELETE_APP);
applink->Attach(&monitor_thread,sizeof(thread_id));
applink->Flush();
#ifdef DEBUG_SERVERAPP_MISC
printf("%s: target application is dead. ServerApp is quitting\n",app_sig.String());
#endif
return false;
}
return true;
}
int32 ServerApp::MonitorApp(void *data)
{
ServerApp *app=(ServerApp *)data;
app->Loop();
exit_thread(0);
return 0;
}
void ServerApp::Loop(void)
{
#ifdef DEBUG_SERVERAPP_MISC
printf("%s: Loop()\n",app_sig.String());
#endif
// Message-dispatching loop for the ServerApp
int32 msgcode;
int8 *msgbuffer=NULL;
ssize_t buffersize,bytesread;
for(;;)
{
buffersize=port_buffer_size(receiver);
if(buffersize>0)
{
// buffers are PortLink messages. Allocate necessary buffer and
// we'll cast it as a BMessage.
msgbuffer=new int8[buffersize];
bytesread=read_port(receiver,&msgcode,msgbuffer,buffersize);
}
else
bytesread=read_port(receiver,&msgcode,NULL,0);
if (bytesread != B_BAD_PORT_ID && bytesread != B_TIMED_OUT && bytesread != B_WOULD_BLOCK)
{
switch(msgcode)
{
// -------------- Messages received from the Application ------------------
case B_QUIT_REQUESTED:
{
// Our BApplication sent us this message when it quit.
// We need to ask the app_server to delete our monitor
port_id serverport=find_port(SERVER_PORT_NAME);
if(serverport==B_NAME_NOT_FOUND)
{
printf("PANIC: ServerApp %s could not find the app_server port!\n",app_sig.String());
break;
}
applink->SetPort(serverport);
applink->SetOpCode(DELETE_APP);
applink->Attach(&monitor_thread,sizeof(thread_id));
applink->Flush();
break;
}
// -------------- Messages received from the Server ------------------------
// Mouse messages simply get passed onto the active app for now
case B_MOUSE_UP:
case B_MOUSE_DOWN:
case B_MOUSE_MOVED:
{
// everything is formatted as it should be, so just call
// write_port. Eventually, this will be replaced by a
// BMessage
write_port(sender, msgcode, msgbuffer, buffersize);
break;
}
case QUIT_APP:
{
// This message is received from the app_server thread
// because the server was asked to quit. Thus, we
// ask all apps to quit. This is NOT the same as system
// shutdown and will happen only in testing
#ifdef DEBUG_SERVERAPP_MSGS
printf("ServerApp asking %s to quit\n",app_sig.String());
#endif
applink->SetOpCode(B_QUIT_REQUESTED);
applink->Flush();
break;
}
default:
{
DispatchMessage(msgcode, msgbuffer);
break;
}
}
}
if(buffersize>0)
delete msgbuffer;
if(msgcode==B_QUIT_REQUESTED)
break;
}
}
void ServerApp::DispatchMessage(int32 code, int8 *buffer)
{
#ifdef DEBUG_SERVERAPP_MSGS
printf("ServerApp ");
PrintMessageCode(code);
#endif
int8 *index=buffer;
LayerData ld;
switch(code)
{
case UPDATED_CLIENT_FONTLIST:
{
// received when the client-side global font list has been
// refreshed
fontserver->Lock();
fontserver->FontsUpdated();
fontserver->Unlock();
break;
}
case CREATE_WINDOW:
{
// Create the ServerWindow to node monitor a new OBWindow
// Attached data:
// 1) port_id reply port
// 2) BRect window frame
// 3) uint32 window flags
// 4) port_id window's message port
// 5) uint32 workspace index
// 6) const char * title
// Find the necessary data
port_id reply_port=*((port_id*)index); index+=sizeof(port_id);
BRect rect=*((BRect*)index); index+=sizeof(BRect);
uint32 winlook=*((uint32*)index); index+=sizeof(uint32);
uint32 winfeel=*((uint32*)index); index+=sizeof(uint32);
uint32 winflags=*((uint32*)index); index+=sizeof(uint32);
port_id win_port=*((port_id*)index); index+=sizeof(port_id);
uint32 workspace=*((uint32*)index); index+=sizeof(uint32);
// Create the ServerWindow object for this window
ServerWindow *newwin=new ServerWindow(rect,(const char *)index,
winlook, winfeel, winflags,this,win_port,workspace);
winlist->AddItem(newwin);
// Window looper is waiting for our reply. Send back the
// ServerWindow's message port
PortLink *replylink=new PortLink(reply_port);
replylink->SetOpCode(SET_SERVER_PORT);
replylink->Attach((int32)newwin->receiver);
replylink->Flush();
delete replylink;
#ifdef DEBUG_SERVERAPP_MSGS
printf("ServerApp: Create Window()\n");
printf("Frame: "); rect.PrintToStream();
printf("Title: %s\n",(const char*)index);
printf("SenderPort: %ld\n",win_port);
printf("Look: 0x%lx\n",winlook);
printf("Feel: 0x%lx\n",winfeel);
printf("Flags: 0x%lx\n",winflags);
printf("Workspace: 0x%lx\n",workspace);
#endif
break;
}
case DELETE_WINDOW:
{
// Received from a ServerWindow when its window quits
// Attached data:
// 1) thread_id ServerWindow ID
thread_id winid;
ServerWindow *w;
for(int32 i=0;i<winlist->CountItems();i++)
{
w=(ServerWindow*)winlist->ItemAt(i);
if(w->thread==winid)
{
winlist->RemoveItem(w);
delete w;
break;
}
}
#ifdef DEBUG_SERVERAPP_MSGS
printf("ServerApp: Delete Window()\n");
printf("Thread ID: %ld",winid);
#endif
break;
}
case GFX_SET_SCREEN_MODE:
{
// Attached data
// 1) int32 workspace #
// 2) uint32 screen mode
// 3) bool make default
int32 workspace=*((int32*)index); index+=sizeof(int32);
uint32 mode=*((uint32*)index); index+=sizeof(uint32);
SetScreenSpace(workspace,mode,*((bool*)index));
#ifdef DEBUG_SERVERAPP_MSGS
printf("ServerApp: SetScreenMode(%ld,%lu,%s)\n",workspace,
mode,(*((bool*)index)==true)?"true":"false");
#endif
break;
}
case GFX_ACTIVATE_WORKSPACE:
{
// Attached data
// 1) int32 workspace index
ActivateWorkspace(*((int32*)index));
#ifdef DEBUG_SERVERAPP_MSGS
printf("ServerApp: ActivateWorkspace(%ld)\n",*((int32*)index));
#endif
break;
}
case SHOW_CURSOR:
{
driver->ShowCursor();
break;
}
case HIDE_CURSOR:
{
driver->HideCursor();
break;
}
case OBSCURE_CURSOR:
{
driver->ObscureCursor();
break;
}
case SET_CURSOR_DATA:
{
// Attached data: 68 bytes of cursor data
// Get the data, update the app's cursor, and update the
// app's cursor if active.
int8 cdata[68];
memcpy(cdata, buffer, 68);
if(cursor)
delete cursor;
cursor=new ServerCursor(cdata);
driver->SetCursor(cursor);
#ifdef DEBUG_SERVERAPP_CURSOR
printf("ServerApp: SetCursor(%d,%d,%d,%d)\n",r,g,b,a);
#endif
break;
}
case SET_CURSOR_BCURSOR:
// Not yet implemented
break;
case SET_CURSOR_BBITMAP:
// Not yet implemented
break;
case GET_FAMILY_ID:
{
// Attached data:
//
break;
}
/* case GFX_DRAW_STRING:
{
// Attached data:
// 1) uint16 string length
// 2) char * string
// 3) BPoint point
uint16 length=*((uint16*)index); index+=sizeof(uint16);
// char *string=new char[length];
// strcpy(string, (const char *)index); index+=length;
BString string=(char *)index; index+=length;
BPoint point=*((BPoint*)index);
#ifdef DEBUG_SERVERAPP_MSGS
printf("ServerApp DrawString(%s, %d, BPoint(%f,%f))\n",string.String(),length,point.x,point.y);
#endif
driver->DrawString((char*)string.String(), length, point);
// delete string;
break;
}
*/
case GFX_STROKE_ARC:
{
// Attached data:
// 1) float center x
// 2) float center y
// 3) float x radius
// 4) float y radius
// 5) float starting angle
// 6) float span (arc length in degrees)
// 7) uint8[8] pattern
float cx,cy,rx,ry,angle,span;
cx=*((float*)index); index+=sizeof(float);
cy=*((float*)index); index+=sizeof(float);
rx=*((float*)index); index+=sizeof(float);
ry=*((float*)index); index+=sizeof(float);
BRect r(cx-rx,cy-ry,cx+rx,cy+ry);
angle=*((float*)index); index+=sizeof(float);
span=*((float*)index); index+=sizeof(float);
#ifdef DEBUG_SERVERAPP_MSGS
printf("ServerApp StrokeArc: ");
printf("Center: %f,%f\n",cx,cy);
printf("Radii: %f,%f\n",rx,ry);
printf("Angle, Span: %f,%f\n",angle, span);
printf("pattern: {%d,%d,%d,%d,%d,%d,%d,%d}\n",index[0],index[1],index[2],index[3],index[4],index[5],index[6],index[7]);
#endif
driver->StrokeArc(r,angle,span,&ld,index);
break;
}
case GFX_STROKE_BEZIER:
{
// Attached data:
// 1) BPoint #1
// 2) BPoint #2
// 3) BPoint #3
// 4) BPoint #4
// 5) uint8[8] pattern
#ifdef DEBUG_SERVERAPP_MSGS
BPoint *pt=(BPoint*)index;
printf("ServerApp StrokeBezier:\n");
printf("Point 1: "); pt[0].PrintToStream();
printf("Point 2: "); pt[1].PrintToStream();
printf("Point 3: "); pt[2].PrintToStream();
printf("Point 4: "); pt[3].PrintToStream();
printf("pattern: {%d,%d,%d,%d,%d,%d,%d,%d}\n",index[0],index[1],index[2],index[3],index[4],index[5],index[6],index[7]);
#endif
driver->StrokeBezier((BPoint*)index,&ld,(int8*)(index+(sizeof(BPoint)*4)));
break;
}
case GFX_STROKE_ELLIPSE:
{
// Attached data:
// 1) float center x
// 2) float center y
// 3) float x radius
// 4) float y radius
// 5) uint8[8] pattern
float cx,cy,rx,ry;
cx=*((float*)index); index+=sizeof(float);
cy=*((float*)index); index+=sizeof(float);
rx=*((float*)index); index+=sizeof(float);
ry=*((float*)index); index+=sizeof(float);
BRect r(cx-rx,cy-ry,cx+rx,cy+ry);
#ifdef DEBUG_SERVERAPP_MSGS
printf("ServerApp StrokeEllipse: ");
printf("Center: %f,%f\n",cx,cy);
printf("Radii: %f,%f\n",rx,ry);
printf("pattern: {%d,%d,%d,%d,%d,%d,%d,%d}\n",index[0],index[1],index[2],index[3],index[4],index[5],index[6],index[7]);
#endif
driver->StrokeEllipse(r,&ld,(int8*)index);
break;
}
case GFX_STROKE_POLYGON:
break;
case GFX_STROKE_RECT:
{
// Attached data:
// 1) BRect rect
// 2) uint8[8] pattern
BRect rect;
rect=*((BRect*)index); index+=sizeof(BRect);
#ifdef DEBUG_SERVERAPP_MSGS
printf("ServerApp StrokeRect: "); rect.PrintToStream();
printf("pattern: {%d,%d,%d,%d,%d,%d,%d,%d}\n",index[0],index[1],index[2],index[3],index[4],index[5],index[6],index[7]);
#endif
driver->StrokeRect(rect,&ld,(int8*)index);
break;
}
case GFX_STROKE_ROUNDRECT:
{
// Attached data:
// 1) BRect rect
// 2) float x_radius
// 3) float y_radius
// 4) uint8[8] pattern
BRect rect;
float x,y;
rect=*((BRect*)index); index+=sizeof(BRect);
x=*((float*)index); index+=sizeof(float);
y=*((float*)index); index+=sizeof(float);
#ifdef DEBUG_SERVERAPP_MSGS
printf("ServerApp StrokeRoundRect: "); rect.PrintToStream();
printf("Radii: %f,%f\n",x,y);
printf("pattern: {%d,%d,%d,%d,%d,%d,%d,%d}\n",index[0],index[1],index[2],index[3],index[4],index[5],index[6],index[7]);
#endif
driver->StrokeRoundRect(rect, x,y,&ld,(int8*)index);
break;
}
case GFX_STROKE_SHAPE:
break;
case GFX_STROKE_TRIANGLE:
{
// Attached data
// 1) BPoint #1
// 2) BPoint #2
// 3) BPoint #3
// 4) BRect invalid rect
// 5) uint8[8] pattern
BRect rect;
rect=*((BRect*)index+(sizeof(BPoint)*3));
#ifdef DEBUG_SERVERAPP_MSGS
printf("ServerApp StrokeTriangle: ");
printf("Point 1: "); ((BPoint*)index)[0].PrintToStream();
printf("Point 2: "); ((BPoint*)index)[1].PrintToStream();
printf("Point 3: "); ((BPoint*)index)[2].PrintToStream();
printf("Rectangle: "); rect.PrintToStream();
printf("pattern: {%d,%d,%d,%d,%d,%d,%d,%d}\n",index[0],index[1],index[2],index[3],index[4],index[5],index[6],index[7]);
#endif
driver->StrokeTriangle((BPoint*)index,rect,&ld,(int8*)(index+(sizeof(BPoint)*3)));
break;
}
case GFX_FILL_ARC:
{
// Attached data:
// 1) float center x
// 2) float center y
// 3) float x radius
// 4) float y radius
// 5) float starting angle
// 6) float span (arc length in degrees)
// 7) uint8[8] pattern
float cx,cy,rx,ry,angle,span;
cx=*((float*)index); index+=sizeof(float);
cy=*((float*)index); index+=sizeof(float);
rx=*((float*)index); index+=sizeof(float);
ry=*((float*)index); index+=sizeof(float);
BRect r(cx-rx,cy-ry,cx+rx,cy+ry);
angle=*((float*)index); index+=sizeof(float);
span=*((float*)index); index+=sizeof(float);
#ifdef DEBUG_SERVERAPP_MSGS
printf("ServerApp FillArc: ");
printf("Center: %f,%f\n",cx,cy);
printf("Radii: %f,%f\n",rx,ry);
printf("Angle, Span: %f,%f\n",angle, span);
printf("pattern: {%d,%d,%d,%d,%d,%d,%d,%d}\n",index[0],index[1],index[2],index[3],index[4],index[5],index[6],index[7]);
#endif
driver->FillArc(r,angle,span,&ld,(int8*)index);
break;
}
case GFX_FILL_BEZIER:
{
// Attached data:
// 1) BPoint #1
// 2) BPoint #2
// 3) BPoint #3
// 4) BPoint #4
// 5) uint8[8] pattern
#ifdef DEBUG_SERVERAPP_MSGS
BPoint *pt=(BPoint*)index;
printf("ServerApp FillBezier:\n");
printf("Point 1: "); pt[0].PrintToStream();
printf("Point 2: "); pt[1].PrintToStream();
printf("Point 3: "); pt[2].PrintToStream();
printf("Point 4: "); pt[3].PrintToStream();
printf("pattern: {%d,%d,%d,%d,%d,%d,%d,%d}\n",index[0],index[1],index[2],index[3],index[4],index[5],index[6],index[7]);
#endif
driver->FillBezier((BPoint*)index,&ld,(int8*)(index+(sizeof(BPoint)*4)));
break;
}
case GFX_FILL_ELLIPSE:
{
// Attached data:
// 1) float center x
// 2) float center y
// 3) float x radius
// 4) float y radius
// 5) uint8[8] pattern
float cx,cy,rx,ry;
cx=*((float*)index); index+=sizeof(float);
cy=*((float*)index); index+=sizeof(float);
rx=*((float*)index); index+=sizeof(float);
ry=*((float*)index); index+=sizeof(float);
BRect r(cx-rx,cy-ry,cx+rx,cy+ry);
#ifdef DEBUG_SERVERAPP_MSGS
printf("ServerApp FillEllipse: ");
printf("Center: %f,%f\n",cx,cy);
printf("Radii: %f,%f\n",rx,ry);
printf("pattern: {%d,%d,%d,%d,%d,%d,%d,%d}\n",index[0],index[1],index[2],index[3],index[4],index[5],index[6],index[7]);
#endif
driver->FillEllipse(r,&ld,(int8*)index);
break;
}
case GFX_FILL_POLYGON:
break;
case GFX_FILL_RECT:
{
// Attached data:
// 1) BRect rect
// 2) uint8[8] pattern
BRect rect;
rect=*((BRect*)index); index+=sizeof(BRect);
#ifdef DEBUG_SERVERAPP_MSGS
printf("ServerApp FillRect: "); rect.PrintToStream();
printf("pattern: {%d,%d,%d,%d,%d,%d,%d,%d}\n",index[0],index[1],index[2],index[3],index[4],index[5],index[6],index[7]);
#endif
driver->FillRect(rect,&ld,(int8*)index);
break;
}
case GFX_FILL_REGION:
break;
case GFX_FILL_ROUNDRECT:
{
// Attached data:
// 1) BRect rect
// 2) float x_radius
// 3) float y_radius
// 4) uint8[8] pattern
BRect rect;
float x,y;
rect=*((BRect*)index); index+=sizeof(BRect);
x=*((float*)index); index+=sizeof(float);
y=*((float*)index); index+=sizeof(float);
#ifdef DEBUG_SERVERAPP_MSGS
printf("ServerApp FillRoundRect: "); rect.PrintToStream();
printf("Radii: %f,%f\n",x,y);
printf("pattern: {%d,%d,%d,%d,%d,%d,%d,%d}\n",index[0],index[1],index[2],index[3],index[4],index[5],index[6],index[7]);
#endif
driver->FillRoundRect(rect,x,y,&ld,(int8*)index);
break;
}
case GFX_FILL_SHAPE:
break;
case GFX_FILL_TRIANGLE:
{
// Attached data
// 1) BPoint #1
// 2) BPoint #2
// 3) BPoint #3
// 4) BRect invalid rect
// 5) uint8[8] pattern
BRect rect;
rect=*((BRect*)index+(sizeof(BPoint)*3));
#ifdef DEBUG_SERVERAPP_MSGS
printf("ServerApp FillTriangle: ");
printf("Point 1: "); ((BPoint*)index)[0].PrintToStream();
printf("Point 2: "); ((BPoint*)index)[1].PrintToStream();
printf("Point 3: "); ((BPoint*)index)[2].PrintToStream();
printf("Rectangle: "); rect.PrintToStream();
printf("pattern: {%d,%d,%d,%d,%d,%d,%d,%d}\n",index[0],index[1],index[2],index[3],index[4],index[5],index[6],index[7]);
#endif
driver->FillTriangle((BPoint*)index,rect,&ld,(int8*)(index+(sizeof(BPoint)*3)));
break;
}
default:
{
#ifdef DEBUG_SERVERAPP_MSGS
cout << "DispatchMessage::Unrecognized code: ";
TranslateMessageCodeToStream(code);
cout << endl << flush;
#endif
break;
}
}
}
// Prevent any preprocessor problems in case I screw something up
#ifdef DEBUG_SERVERAPP_MSGS
#undef DEBUG_SERVERAPP_MSGS
#endif
#ifdef DEBUG_SERVERAPP_CURSORS
#undef DEBUG_SERVERAPP_CURSORS
#endif

View File

@ -0,0 +1,42 @@
#ifndef _SRVAPP_H_
#define _SRVAPP_H_
#include <OS.h>
#include <String.h>
class BMessage;
class PortLink;
class BList;
class ServerCursor;
class DisplayDriver;
class ServerApp
{
public:
ServerApp(port_id msgport, char *signature);
~ServerApp(void);
bool Run(void);
static int32 MonitorApp(void *data);
void Loop(void);
bool IsActive(void) const { return isactive; }
void Activate(bool value) { isactive=value; }
bool PingTarget(void);
// char *app_sig;
port_id sender,receiver;
BString app_sig;
thread_id monitor_thread;
PortLink *applink;
BList *winlist, *bmplist;
ServerCursor *cursor;
DisplayDriver *driver;
rgb_color high, low; // just for testing until layers are implemented
protected:
void DispatchMessage(int32 code, int8 *buffer);
bool isactive;
team_id target_id;
};
#endif

View File

@ -0,0 +1,250 @@
/*
ServerBitmap.cpp
Bitmap class which is intended to provide an easy way to package all the
data associated with a picture. It's very low-level, so there's still
plenty to do when coding with 'em. Also, they can be used to access draw on the
frame buffer in a relatively easy way, although it is currently unclear
whether this functionality will even be necessary.
*/
// These three includes for ServerBitmap(const char *path_to_image_file) only
#include <TranslationUtils.h>
#include <string.h>
#include <Bitmap.h>
#include <assert.h>
#include "ServerBitmap.h"
#include "Desktop.h"
#include "DisplayDriver.h"
//#define DEBUG_BITMAP
#ifdef DEBUG_BITMAP
#include <stdio.h>
#endif
ServerBitmap::ServerBitmap(BRect rect,color_space space,int32 BytesPerLine=0)
{
width=rect.IntegerWidth()+1;
height=rect.IntegerHeight()+1;
cspace=space;
areaid=B_ERROR;
HandleSpace(space, BytesPerLine);
buffer=new uint8[bytesperline*height];
}
ServerBitmap::ServerBitmap(int32 w,int32 h,color_space space,int32 BytesPerLine=0)
{
width=w;
height=h;
cspace=space;
areaid=B_ERROR;
HandleSpace(space, BytesPerLine);
buffer=new uint8[bytesperline*height];
}
// This particular version is not intended for use except for testing purposes.
// It loads a BBitmap and copies it to the ServerBitmap. Probably will disappear
// when the *real* server is written
ServerBitmap::ServerBitmap(const char *path)
{
if(!path)
{
width=0;
height=0;
cspace=B_NO_COLOR_SPACE;
bytesperline=0;
return;
}
BBitmap *bmp=BTranslationUtils::GetBitmap(path);
assert(bmp!=NULL);
if(bmp==NULL)
{
width=0;
height=0;
cspace=B_NO_COLOR_SPACE;
bytesperline=0;
}
else
{
width=bmp->Bounds().IntegerWidth();
height=bmp->Bounds().IntegerHeight();
cspace=bmp->ColorSpace();
bytesperline=bmp->BytesPerRow();
buffer=new uint8[bmp->BitsLength()];
memcpy(buffer,(void *)bmp->Bits(),bmp->BitsLength());
}
}
ServerBitmap::ServerBitmap(ServerBitmap *bitmap)
{
width=bitmap->width;
height=bitmap->height;
cspace=bitmap->cspace;
areaid=B_ERROR;
HandleSpace(bitmap->cspace, bitmap->bytesperline);
buffer=new uint8[bytesperline*height];
memcpy(buffer, bitmap->buffer, bytesperline * height);
}
ServerBitmap::~ServerBitmap(void)
{
if(buffer)
delete buffer;
}
void ServerBitmap::UpdateSettings(void)
{
// This is only used when the object is pointing to the frame buffer
bpp=driver->GetDepth();
width=driver->GetWidth();
height=driver->GetHeight();
}
uint8 *ServerBitmap::Bits(void)
{
return buffer;
}
uint32 ServerBitmap::BitsLength(void)
{
return (uint32)(bytesperline*height);
}
void ServerBitmap::HandleSpace(color_space space, int32 BytesPerLine)
{
// Function written to handle color space setup which is required
// by the two "normal" constructors
// Big convoluted mess just to handle every color space and dword align
// the buffer
switch(space)
{
// Buffer is dword-aligned, so nothing need be done
// aside from allocate the memory
case B_RGB32:
case B_RGBA32:
case B_RGB32_BIG:
case B_RGBA32_BIG:
case B_UVL32:
case B_UVLA32:
case B_LAB32:
case B_LABA32:
case B_HSI32:
case B_HSIA32:
case B_HSV32:
case B_HSVA32:
case B_HLS32:
case B_HLSA32:
case B_CMY32:
case B_CMYA32:
case B_CMYK32:
// 24-bit = 32-bit with extra 8 bits ignored
case B_RGB24_BIG:
case B_RGB24:
case B_LAB24:
case B_UVL24:
case B_HSI24:
case B_HSV24:
case B_HLS24:
case B_CMY24:
{
if(BytesPerLine<(width*4))
bytesperline=width*4;
else
bytesperline=BytesPerLine;
bpp=32;
break;
}
// Calculate size and dword-align
// 1-bit
case B_GRAY1:
{
int32 numbytes=width>>3;
if((width % 8) != 0)
numbytes++;
if(BytesPerLine<numbytes)
{
for(int8 i=0;i<4;i++)
{
if( (numbytes+i)%4==0)
{
bytesperline=numbytes+i;
break;
}
}
}
else
bytesperline=BytesPerLine;
bpp=1;
}
// 8-bit
case B_CMAP8:
case B_GRAY8:
case B_YUV411:
case B_YUV420:
case B_YCbCr422:
case B_YCbCr411:
case B_YCbCr420:
case B_YUV422:
{
if(BytesPerLine<width)
{
for(int8 i=0;i<4;i++)
{
if( (width+i)%4==0)
{
bytesperline=width+i;
break;
}
}
}
else
bytesperline=BytesPerLine;
bpp=8;
break;
}
// 16-bit
case B_YUV9:
case B_YUV12:
case B_RGB15:
case B_RGBA15:
case B_RGB16:
case B_RGB16_BIG:
case B_RGB15_BIG:
case B_RGBA15_BIG:
case B_YCbCr444:
case B_YUV444:
{
if(BytesPerLine<width*2)
{
if( (width*2) % 4 !=0)
bytesperline=(width+1)*2;
else
bytesperline=width*2;
}
else
bytesperline=BytesPerLine;
bpp=16;
break;
}
case B_NO_COLOR_SPACE:
bpp=0;
break;
}
#ifdef DEBUG_BITMAP
printf("ServerBitmap::HandleSpace():\n");
printf("Bytes per line: %ld\n",bytesperline);
printf("Width: %ld Height: %ld\n",width, height);
#endif
}

View File

@ -0,0 +1,42 @@
#ifndef _SERVER_BITMAP_H_
#define _SERVER_BITMAP_H_
#include <GraphicsDefs.h>
#include <Rect.h>
#include <OS.h>
class DisplayDriver;
class ServerBitmap
{
public:
ServerBitmap(BRect rect,color_space space,int32 BytesPerLine=0);
ServerBitmap(int32 w,int32 h,color_space space,int32 BytesPerLine=0);
ServerBitmap(const char *path);
ServerBitmap(ServerBitmap *bitmap);
~ServerBitmap(void);
void UpdateSettings(void);
void SetBuffer(void *ptr) { buffer=(uint8*)ptr; }
void FreeBuffer(void) { if(buffer!=NULL) { delete buffer; buffer=NULL; } }
uint8 *Bits(void);
void SetArea(area_id ID);
area_id Area(void);
uint32 BitsLength(void);
BRect Bounds() { return BRect(0,0,width-1,height-1); };
int32 BytesPerRow(void) { return bytesperline; };
uint8 BitsPerPixel(void) { return bpp; }
color_space ColorSpace(void) { return cspace; }
int32 width,height;
int32 bytesperline;
color_space cspace;
int bpp;
protected:
void HandleSpace(color_space space, int32 BytesPerLine);
DisplayDriver *driver;
area_id areaid;
uint8 *buffer;
};
#endif

View File

@ -0,0 +1,113 @@
/*
ServerCursor.cpp
This is the server-side class used to handle cursors. Note that it
will handle the R5 cursor API, but it will also handle taking a bitmap.
ServerCursors are 32-bit. Eventually, we will be mapping colors to fit
when the set is called.
This is new code, and there may be changes to the API before it settles
in.
*/
#include "ServerCursor.h"
#include <stdio.h>
#include <math.h>
long pow2(int power)
{
if(power==0)
return 1;
return long(2 << (power-1));
}
//#define DEBUG_SERVER_CURSOR
/*
ServerCursor::ServerCursor(ServerBitmap *bmp, ServerBitmap *cmask=NULL)
{
// The OpenBeOS R1 API can use Bitmaps to create cursors - more flexibility that way.
}
*/
ServerCursor::ServerCursor(int8 *data)
{
// 68-byte array used in R5 for holding cursors.
// This API has serious problems and should be deprecated(but supported) in R2
// Now that we have all the setup, we're going to map (for now) the cursor
// to RGBA32. Eventually, there will be support for 16 and 8-bit depths
if(data)
{
uint32 black=0xFF000000,
white=0xFFFFFFFF,
*bmppos;
uint16 *cursorpos, *maskpos,cursorflip, maskflip,
cursorval, maskval;
uint8 i,j;
cursorpos=(uint16*)(data+4);
maskpos=(uint16*)(data+36);
buffer=new uint8[1024]; // 16x16x4 - RGBA32 space
width=16;
height=16;
bytesperline=64;
// for each row in the cursor data
for(j=0;j<16;j++)
{
bmppos=(uint32*)(buffer+ (j*64) );
// On intel, our bytes end up swapped, so we must swap them back
cursorflip=(cursorpos[j] & 0xFF) << 8;
cursorflip |= (cursorpos[j] & 0xFF00) >> 8;
maskflip=(maskpos[j] & 0xFF) << 8;
maskflip |= (maskpos[j] & 0xFF00) >> 8;
// for each column in each row of cursor data
for(i=0;i<16;i++)
{
// Get the values and dump them to the bitmap
cursorval=cursorflip & pow2(15-i);
maskval=maskflip & pow2(15-i);
bmppos[i]=((cursorval!=0)?black:white) & ((maskval>0)?0xFFFFFFFF:0x00FFFFFF);
}
}
}
else
{
buffer=NULL;
width=0;
height=0;
bytesperline=0;
}
#ifdef DEBUG_SERVER_CURSOR
PrintToStream();
#endif
}
ServerCursor::~ServerCursor(void)
{
if(buffer)
delete buffer;
}
void ServerCursor::PrintToStream(void)
{
if(!buffer)
{
printf("ServerCursor with NULL buffer\n");
return;
}
rgb_color *color=(rgb_color*)buffer;
printf("Server Cursor\n");
for(int32 i=0; i<height; i++)
{
for(int32 j=0; j<width; j++)
printf("%c ", (color[(i*height)+j].alpha>0)?'*':'.');
printf("\n");
}
}

View File

@ -0,0 +1,26 @@
#ifndef _SERVER_CURSOR_H
#define _SERVER_CURSOR_H
#include <GraphicsDefs.h>
#include <Rect.h>
#include "ServerBitmap.h"
class ServerCursor
{
public:
// ServerCursor(ServerBitmap *bmp,ServerBitmap *cmask=NULL);
ServerCursor(int8 *data);
~ServerCursor(void);
BRect Bounds() { return BRect(0,0,width-1,height-1); };
uint8 *Buffer(void) const { return buffer;}
int32 Width(void) const { return width; }
int32 Height(void) const { return height; }
int32 BytesPerLine(void) const { return bytesperline; };
void PrintToStream(void);
protected:
uint8 *buffer;
int32 width,height;
int32 bytesperline;
};
#endif

View File

@ -0,0 +1,65 @@
/*
This class is the shadow class to BFont. The only problem is that
FreeType is going to need to be, um, "customized" to do everything
we need it to do, such as the file format, other encodings, etc.
*/
#include "FontFamily.h"
#include "ServerFont.h"
ServerFont::ServerFont(FontStyle *style, float size=12.0, float rotation=0.0, float shear=90.0,
uint16 flags=0, uint8 spacing=B_CHAR_SPACING)
{
fstyle=style;
fsize=size;
frotation=rotation;
fshear=shear;
fflags=flags;
fspacing=spacing;
fdirection=B_FONT_LEFT_TO_RIGHT;
fface=B_REGULAR_FACE;
ftruncate=B_TRUNCATE_END;
fencoding=B_UNICODE_UTF8;
if(fstyle)
fstyle->AddDependent();
}
ServerFont::ServerFont(const ServerFont &font)
{
fstyle=font.fstyle;
fsize=font.fsize;
frotation=font.frotation;
fshear=font.fshear;
fflags=font.fflags;
fspacing=font.fspacing;
fdirection=font.fdirection;
fface=font.fface;
ftruncate=font.ftruncate;
fencoding=font.fencoding;
if(fstyle)
fstyle->AddDependent();
}
ServerFont::~ServerFont(void)
{
if(fstyle)
fstyle->RemoveDependent();
}
/* TODO: implement these functions
BRect BoundingBox(void)
{
}
escapement_delta Escapements(char c)
{
}
*/
void ServerFont::Height(font_height *fh)
{
fh->ascent=fheight.ascent;
fh->descent=fheight.descent;
fh->leading=fheight.leading;
}

View File

@ -0,0 +1,56 @@
#ifndef SERVERFONT_H_
#define SERVERFONT_H_
#include <Rect.h>
#include <Font.h>
class FontStyle;
class ServerFont
{
public:
ServerFont(FontStyle *fstyle, float fsize=12.0, float frotation=0.0, float fshear=90.0,
uint16 flags=0, uint8 spacing=B_CHAR_SPACING);
ServerFont(const ServerFont &font);
~ServerFont(void);
font_direction Direction(void) { return fdirection; }
uint8 Encoding(void) { return fencoding; }
edge_info Edges(void) { return fedges; }
uint32 Flags(void) { return fflags; }
uint8 Spacing(void) { return fspacing; }
float Shear(void) { return fshear; }
float Rotation(void) { return frotation; }
float Size(void) { return fsize; }
uint16 Face(void) { return fface; }
uint32 CountGlyphs(void);
FontStyle *Style(void) { return fstyle; }
void SetDirection(const font_direction &dir) { fdirection=dir; }
void SetEdges(const edge_info &info) { fedges=info; }
void SetEncoding(uint8 encoding) { fencoding=encoding; }
void SetFlags(const uint32 &value) { fflags=value; }
void SetSpacing(const uint8 &value) { fspacing=value; }
void SetShear(const float &value) { fshear=value; }
void SetSize(const float &value) { fsize=value; }
void SetRotation(const float &value) { frotation=value; }
void SetFace(const uint16 &value) { fface=value; }
// BRect BoundingBox(void);
// escapement_delta Escapements(char c);
void Height(font_height *fh);
protected:
friend FontStyle;
FontStyle *fstyle;
font_height fheight;
escapement_delta fescapements;
edge_info fedges;
float fsize, frotation, fshear;
uint32 fflags;
uint8 fspacing;
uint16 fface;
font_direction fdirection;
uint8 ftruncate;
uint8 fencoding;
};
#endif

View File

@ -0,0 +1,121 @@
#ifndef _APPSERVER_PROTOCOL_
#define _APPSERVER_PROTOCOL_
#define CREATE_APP 'drca'
#define DELETE_APP 'drda'
#define QUIT_APP 'srqa'
#define SET_SERVER_PORT 'srsp'
#define CREATE_WINDOW 'drcw'
#define DELETE_WINDOW 'drdw'
#define SHOW_WINDOW 'drsw'
#define HIDE_WINDOW 'drhw'
#define QUIT_WINDOW 'srqw'
#define SERVER_PORT_NAME "OBappserver"
#define SERVER_INPUT_PORT "OBinputport"
#define SERVER_FONT_LIST "/boot/home/config/settings/app_server/fontlist"
#define SERVER_SETTINGS_DIR "/boot/home/config/settings/app_server/"
#define COLOR_SET_DIR "/boot/home/config/settings/color_sets/"
#define DECORATORS_DIR "/boot/home/config/add-ons/decorators/"
#define COLOR_SETTINGS_NAME "system_colors"
// Used for quick replies from the app_server
#define SERVER_TRUE 'svtr'
#define SERVER_FALSE 'svfl'
// Font-related server communications
#define QUERY_FONTS_CHANGED 'qfch'
#define UPDATED_CLIENT_FONTLIST 'ucfl'
#define GET_FAMILY_ID 'fmid'
#define GET_STYLE_ID 'stid'
#define GET_STYLE_FOR_FACE 'stff'
// This will be modified. Currently a kludge for the input server until
// BScreens are implemented by the IK Taeam
#define GET_SCREEN_MODE 'gsmd'
#define SET_UI_COLORS 'suic'
#define GET_UI_COLOR 'guic'
#define SET_DECORATOR 'sdec'
#define GET_DECORATOR 'gdec'
#define SET_CURSOR_DATA 'sscd'
#define SET_CURSOR_BCURSOR 'sscb'
#define SET_CURSOR_BBITMAP 'sscB'
#define SHOW_CURSOR 'srsc'
#define HIDE_CURSOR 'srhc'
#define OBSCURE_CURSOR 'sroc'
#define GFX_COUNT_WORKSPACES 'gcws'
#define GFX_SET_WORKSPACE_COUNT 'ggwc'
#define GFX_CURRENT_WORKSPACE 'ggcw'
#define GFX_ACTIVATE_WORKSPACE 'gaws'
#define GFX_GET_SYSTEM_COLORS 'gsyc'
#define GFX_SET_SYSTEM_COLORS 'gsyc'
#define GFX_SET_SCREEN_MODE 'gssm'
#define GFX_GET_SCROLLBAR_INFO 'ggsi'
#define GFX_SET_SCROLLBAR_INFO 'gssi'
#define GFX_IDLE_TIME 'gidt'
#define GFX_SELECT_PRINTER_PANEL 'gspp'
#define GFX_ADD_PRINTER_PANEL 'gapp'
#define GFX_RUN_BE_ABOUT 'grba'
#define GFX_SET_FOCUS_FOLLOWS_MOUSE 'gsfm'
#define GFX_FOCUS_FOLLOWS_MOUSE 'gffm'
#define GFX_SET_HIGH_COLOR 'gshc'
#define GFX_SET_LOW_COLOR 'gslc'
#define GFX_SET_VIEW_COLOR 'gsvc'
#define GFX_STROKE_ARC 'gsar'
#define GFX_STROKE_BEZIER 'gsbz'
#define GFX_STROKE_ELLIPSE 'gsel'
#define GFX_STROKE_LINE 'gsln'
#define GFX_STROKE_POLYGON 'gspy'
#define GFX_STROKE_RECT 'gsrc'
#define GFX_STROKE_ROUNDRECT 'gsrr'
#define GFX_STROKE_SHAPE 'gssh'
#define GFX_STROKE_TRIANGLE 'gstr'
#define GFX_FILL_ARC 'gfar'
#define GFX_FILL_BEZIER 'gfbz'
#define GFX_FILL_ELLIPSE 'gfel'
#define GFX_FILL_POLYGON 'gfpy'
#define GFX_FILL_RECT 'gfrc'
#define GFX_FILL_REGION 'gfrg'
#define GFX_FILL_ROUNDRECT 'gfrr'
#define GFX_FILL_SHAPE 'gfsh'
#define GFX_FILL_TRIANGLE 'gftr'
#define GFX_MOVEPENBY 'gmpb'
#define GFX_MOVEPENTO 'gmpt'
#define GFX_SETPENSIZE 'gsps'
#define GFX_DRAW_STRING 'gdst'
#define GFX_SET_FONT 'gsft'
#define GFX_SET_FONT_SIZE 'gsfs'
#define GFX_FLUSH 'gfsh'
#define GFX_SYNC 'gsyn'
#define LAYER_CREATE 'lycr'
#define LAYER_DELETE 'lydl'
#define LAYER_ADD_CHILD 'lyac'
#define LAYER_REMOVE_CHILD 'lyrc'
#define LAYER_REMOVE_SELF 'lyrs'
#define LAYER_SHOW 'lysh'
#define LAYER_HIDE 'lyhd'
#define LAYER_MOVE 'lymv'
#define LAYER_RESIZE 'lyre'
#define LAYER_INVALIDATE 'lyin'
#define LAYER_DRAW 'lydr'
#define BEGIN_RECT_TRACKING 'rtbg'
#define END_RECT_TRACKING 'rten'
#define VIEW_GET_TOKEN 'vgtk'
#define VIEW_ADD 'vadd'
#define VIEW_REMOVE 'vrem'
#endif

View File

@ -0,0 +1,508 @@
/*
ServerWindow.cpp
Class which works with a BWindow. Handles all messages coming from and
going to its window plus all drawing calls.
*/
#include <AppDefs.h>
#include <Rect.h>
#include <string.h>
#include <stdio.h>
#include <Debug.h>
#include <View.h> // for B_XXXXX_MOUSE_BUTTON defines
#include "AppServer.h"
#include "Layer.h"
#include "PortLink.h"
#include "ServerWindow.h"
#include "ServerApp.h"
#include "ServerProtocol.h"
#include "WindowBorder.h"
#include "DebugTools.h"
#include "Desktop.h"
//#define DEBUG_SERVERWIN
// Used for providing identifiers for views
int32 view_counter=0;
// Used in window focus management
ServerWindow *active_serverwindow=NULL;
ServerWindow::ServerWindow(BRect rect, const char *string, uint32 wlook,
uint32 wfeel, uint32 wflags, ServerApp *winapp, port_id winport, uint32 index)
{
title=new BString;
if(string)
title->SetTo(string);
else
title->SetTo("Window");
#ifdef DEBUG_SERVERWIN
printf("ServerWindow() %s\n",title->String());
#endif
// This must happen before the WindowBorder object - it needs this object's frame
// to be valid
frame=rect;
// set these early also - the decorator will also need them
winflags=wflags;
winlook=wlook;
winfeel=wfeel;
winborder=new WindowBorder(this, title->String());
// hard code this for now - window look also needs to be attached and sent to
// server by BWindow constructor
decorator=instantiate_decorator(frame,winlook,winfeel,winflags);
#ifdef DEBUG_SERVERWIN
if(decorator==NULL)
printf("ServerWindow() %s: NULL decorator returned\n",title->String());
#endif
winborder->SetDecorator(decorator);
#ifdef DEBUG_SERVERWIN
printf("ServerWindow() %s: decorator set\n",title->String());
#endif
// sender is the monitored app's event port
sender=winport;
winlink=new PortLink(sender);
if(winapp!=NULL)
applink=new PortLink(winapp->receiver);
else
applink=NULL;
#ifdef DEBUG_SERVERWIN
printf("ServerWindow() %s: PortLink established\n",title->String());
#endif
// receiver is the port to which the app sends messages for the server
receiver=create_port(30,title->String());
active=false;
hidecount=0;
// Spawn our message monitoring thread
thread=spawn_thread(MonitorWin,title->String(),B_NORMAL_PRIORITY,this);
if(thread!=B_NO_MORE_THREADS && thread!=B_NO_MEMORY)
resume_thread(thread);
#ifdef DEBUG_SERVERWIN
printf("ServerWindow() %s: MonitorThread spawned\n",title->String());
#endif
workspace=index;
AddWindowToDesktop(this,index);
#ifdef DEBUG_SERVERWIN
printf("ServerWindow() %s: Added to Desktop\n",title->String());
#endif
}
ServerWindow::~ServerWindow(void)
{
#ifdef DEBUG_SERVERWIN
printf("%s::~ServerWindow()\n",title->String());
#endif
RemoveWindowFromDesktop(this);
if(applink)
{
delete applink;
applink=NULL;
delete title;
delete winlink;
delete decorator;
delete winborder;
}
kill_thread(thread);
}
void ServerWindow::RequestDraw(BRect rect)
{
winlink->SetOpCode(LAYER_DRAW);
winlink->Attach(&rect,sizeof(BRect));
winlink->Flush();
}
void ServerWindow::ReplaceDecorator(void)
{
#ifdef DEBUG_SERVERWIN
printf("%s::ReplaceDecorator()\n",title->String());
#endif
}
void ServerWindow::Quit(void)
{
#ifdef DEBUG_SERVERWIN
printf("%s::Quit()\n",title->String());
#endif
}
const char *ServerWindow::GetTitle(void)
{
return title->String();
}
ServerApp *ServerWindow::GetApp(void)
{
return app;
}
void ServerWindow::Show(void)
{
#ifdef DEBUG_SERVERWIN
printf("%s::Show()\n",title->String());
#endif
if(winborder)
{
winborder->ShowLayer();
ActivateWindow(this);
// winborder->Draw(frame);
}
}
void ServerWindow::Hide(void)
{
#ifdef DEBUG_SERVERWIN
printf("%s::Hide()\n",title->String());
#endif
if(winborder)
winborder->HideLayer();
}
bool ServerWindow::IsHidden(void)
{
return (hidecount==0)?true:false;
}
void ServerWindow::SetFocus(bool value)
{
#ifdef DEBUG_SERVERWIN
printf("%s::SetFocus(%s)\n",title->String(),(value==true)?"true":"false");
#endif
if(active!=value)
{
active=value;
decorator->SetFocus(value);
decorator->Draw();
}
}
bool ServerWindow::HasFocus(void)
{
return active;
}
void ServerWindow::WorkspaceActivated(int32 NewWorkspace, const BPoint Resolution, color_space CSpace)
{
}
void ServerWindow::WindowActivated(bool Active)
{
}
void ServerWindow::ScreenModeChanged(const BPoint Resolustion, color_space CSpace)
{
}
void ServerWindow::SetFrame(const BRect &rect)
{
#ifdef DEBUG_SERVERWIN
printf("%s::SetFrame()",title->String()); rect.PrintToStream();
#endif
frame=rect;
}
BRect ServerWindow::Frame(void)
{
return frame;
}
status_t ServerWindow::Lock(void)
{
#ifdef DEBUG_SERVERWIN
printf("%s::Lock()\n",title->String());
#endif
return locker.Lock();
}
void ServerWindow::Unlock(void)
{
#ifdef DEBUG_SERVERWIN
printf("%s::Unlock()\n",title->String());
#endif
locker.Unlock();
}
bool ServerWindow::IsLocked(void)
{
return locker.IsLocked();
}
void ServerWindow::Loop(void)
{
// Message-dispatching loop for the ServerWindow
#ifdef DEBUG_SERVERWIN
printf("%s::Loop()\n",title->String());
#endif
int32 msgcode;
int8 *msgbuffer=NULL;
ssize_t buffersize,bytesread;
for(;;)
{
buffersize=port_buffer_size(receiver);
if(buffersize>0)
{
msgbuffer=new int8[buffersize];
bytesread=read_port(receiver,&msgcode,msgbuffer,buffersize);
}
else
bytesread=read_port(receiver,&msgcode,NULL,0);
if (bytesread != B_BAD_PORT_ID && bytesread != B_TIMED_OUT && bytesread != B_WOULD_BLOCK)
{
switch(msgcode)
{
case LAYER_CREATE:
{
// Received when a view is attached to a window. This will require
// us to attach a layer in the tree in the same manner and invalidate
// the area in which the new layer resides assuming that it is
// visible
// Attached Data:
// 1) (int32) id of the parent view
// 2) (int32) id of the child view
// 3) (BRect) frame in parent's coordinates
// 4) (int32) resize flags
// 5) (int32) view flags
// 6) (uint16) view's hide level
break;
}
case LAYER_DELETE:
{
// Received when a view is detached from a window. This is definitely
// the less taxing operation - we call PruneTree() on the removed
// layer, detach the layer itself, delete it, and invalidate the
// area assuming that the view was visible when removed
// Attached Data:
// 1) (int32) id of the removed view
break;
}
case SHOW_WINDOW:
{
Show();
break;
}
case HIDE_WINDOW:
{
Hide();
break;
}
case DELETE_WINDOW:
{
// Received from our window when it is told to quit, so tell our
// application to delete this object
applink->SetOpCode(DELETE_WINDOW);
applink->Attach((int32)thread);
applink->Flush();
break;
}
case VIEW_GET_TOKEN:
{
// Request to get a view identifier - this is synchronous, so reply
// immediately
// Attached data:
// 1) port_id reply port
port_id reply_port=*((port_id*)msgbuffer);
PortLink *link=new PortLink(reply_port);
link->Attach(view_counter++);
link->Flush();
break;
}
default:
DispatchMessage(msgcode,msgbuffer);
break;
}
}
if(buffersize>0)
delete msgbuffer;
if(msgcode==B_QUIT_REQUESTED)
break;
}
}
void ServerWindow::DispatchMessage(int32 code, int8 *msgbuffer)
{
switch(code)
{
default:
{
#ifdef DEBUG_SERVERWIN
printf("%s::ServerWindow(): Received unexpected code: ",title->String());
PrintMessageCode(code);
#endif
break;
}
}
}
int32 ServerWindow::MonitorWin(void *data)
{
ServerWindow *win=(ServerWindow *)data;
win->Loop();
exit_thread(0);
return 0;
}
void ServerWindow::HandleMouseEvent(int32 code, int8 *buffer)
{
ServerWindow *mousewin=NULL;
int8 *index=buffer;
// Find the window which will receive our mouse event.
Layer *root=GetRootLayer();
WindowBorder *winborder;
ASSERT(root!=NULL);
// Dispatch the mouse event to the proper window
switch(code)
{
case B_MOUSE_DOWN:
{
// Attached data:
// 1) int64 - time of mouse click
// 2) float - x coordinate of mouse click
// 3) float - y coordinate of mouse click
// 4) int32 - modifier keys down
// 5) int32 - buttons down
// 6) int32 - clicks
// int64 time=*((int64*)index);
index+=sizeof(int64);
float x=*((float*)index);
index+=sizeof(float);
float y=*((float*)index);
index+=sizeof(float);
int32 modifiers=*((int32*)index);
index+=sizeof(uint32);
uint32 buttons=*((uint32*)index);
index+=sizeof(uint32);
// int32 clicks=*((int32*)index);
BPoint pt(x,y);
// If we have clicked on a window,
winborder=(WindowBorder*)root->GetChildAt(pt);
if(winborder)
{
mousewin=winborder->Window();
ASSERT(mousewin!=NULL);
winborder->MouseDown(pt,buttons,modifiers);
#ifdef DEBUG_SERVERWIN
printf("ServerWindow() %s: MouseDown(%.1f,%.1f)\n",mousewin->title->String(),x,y);
#endif
}
break;
}
case B_MOUSE_UP:
{
// Attached data:
// 1) int64 - time of mouse click
// 2) float - x coordinate of mouse click
// 3) float - y coordinate of mouse click
// 4) int32 - modifier keys down
// int64 time=*((int64*)index);
index+=sizeof(int64);
float x=*((float*)index);
index+=sizeof(float);
float y=*((float*)index);
index+=sizeof(float);
// int32 modifiers=*((int32*)index);
BPoint pt(x,y);
is_moving_window=false;
winborder=(WindowBorder*)root->GetChildAt(pt);
if(winborder)
{
mousewin=winborder->Window();
ASSERT(mousewin!=NULL);
// Eventually, we will build in MouseUp messages with buttons specified
// For now, we just "assume" no mouse specification with a 0.
winborder->MouseUp(pt,0,0);
// Do cool mouse stuff here
#ifdef DEBUG_SERVERWIN
printf("ServerWindow() %s: MouseUp(%.1f,%.1f)\n",mousewin->title->String(),x,y);
#endif
}
break;
}
case B_MOUSE_MOVED:
{
// Attached data:
// 1) int64 - time of mouse click
// 2) float - x coordinate of mouse click
// 3) float - y coordinate of mouse click
// 4) int32 - buttons down
// int64 time=*((int64*)index);
index+=sizeof(int64);
float x=*((float*)index);
index+=sizeof(float);
float y=*((float*)index);
index+=sizeof(float);
uint32 buttons=*((uint32*)index);
BPoint pt(x,y);
if(!is_moving_window)
{
winborder=(WindowBorder*)root->GetChildAt(pt);
if(winborder)
{
mousewin=winborder->Window();
ASSERT(mousewin!=NULL);
winborder->MouseMoved(pt,buttons,0);
}
}
else
{
mousewin=active_serverwindow;
ASSERT(mousewin!=NULL);
mousewin->winborder->MouseMoved(pt,buttons,0);
}
break;
}
default:
{
#ifdef DEBUG_SERVERWIN
printf("HandleMouseEvent() received an unrecognized mouse event");
PrintMessageCode(code);
#endif
break;
}
}
}
void ActivateWindow(ServerWindow *win)
{
if(active_serverwindow==win)
return;
if(active_serverwindow)
active_serverwindow->SetFocus(false);
active_serverwindow=win;
if(win)
win->SetFocus(true);
}

View File

@ -0,0 +1,76 @@
#ifndef _SERVERWIN_H_
#define _SERVERWIN_H_
#include <SupportDefs.h>
#include <GraphicsDefs.h>
#include <OS.h>
#include <Locker.h>
#include <Rect.h>
#include <String.h>
class BString;
class BMessenger;
class BPoint;
class ServerApp;
class Decorator;
class PortLink;
class WindowBorder;
class ServerWindow
{
public:
ServerWindow(BRect rect, const char *string, uint32 wlook, uint32 wfeel,
uint32 wflags, ServerApp *winapp, port_id winport, uint32 index);
~ServerWindow(void);
void ReplaceDecorator(void);
void Quit(void);
const char *GetTitle(void);
ServerApp *GetApp(void);
void Show(void);
void Hide(void);
bool IsHidden(void);
void SetFocus(bool value);
bool HasFocus(void);
void RequestDraw(BRect rect);
void WorkspaceActivated(int32 NewDesktop, const BPoint Resolution, color_space CSpace);
void WindowActivated(bool Active);
void ScreenModeChanged(const BPoint Resolution, color_space CSpace);
void SetFrame(const BRect &rect);
BRect Frame(void);
status_t Lock(void);
void Unlock(void);
bool IsLocked(void);
void DispatchMessage(int32 code, int8 *msgbuffer);
static int32 MonitorWin(void *data);
static void HandleMouseEvent(int32 code, int8 *buffer);
void Loop(void);
BString *title;
int32 winlook, winfeel, winflags;
int32 workspace;
bool active;
ServerApp *app;
Decorator *decorator;
WindowBorder *winborder;
bigtime_t lasthit; // Time of last mouse click
thread_id thread;
port_id receiver; // Messages from window
port_id sender; // Messages to window
PortLink *winlink,*applink;
BLocker locker;
BRect frame;
uint8 hidecount;
};
void ActivateWindow(ServerWindow *win);
#endif

View File

@ -0,0 +1,23 @@
#ifndef SHAREDOBJ_H_
#define SHAREDOBJ_H_
/*
This class is used as a base class for other objects which must be shared.
By using this, objects which depend on its existence can be somewhat sure
that the shared object will not be deleted until nothing depends on it.
*/
#include <SupportDefs.h>
class SharedObject
{
public:
SharedObject(void) { dependents=0; }
virtual ~SharedObject(void){}
virtual void AddDependent(void) { dependents++; }
virtual void RemoveDependent(void) { dependents--; }
virtual bool HasDependents(void) { return (dependents>0)?true:false; }
private:
uint32 dependents;
};
#endif

View File

@ -0,0 +1,328 @@
/*
SystemPalette.cpp
One global function to generate the palette which is the default BeOS
System palette and the variable to go with it
*/
#include "SystemPalette.h"
rgb_color system_palette[256];
void GenerateSystemPalette(rgb_color *palette)
{
int i,j,index=0;
int indexvals1[]={ 255,229,204,179,154,129,105,80,55,30 },
indexvals2[]={ 255,203,152,102,51,0 };
// ff, cb, 98, 66, 33
rgb_color *currentcol;
// Grays 0,0,0 -> 248,248,248 by 8's
for(i=0; i<=248; i+=8,index++)
{
currentcol=&(palette[index]);
currentcol->red=i;
currentcol->green=i;
currentcol->blue=i;
currentcol->alpha=255;
}
// Blues, following indexvals1
for(i=0; i<10; i++,index++)
{
currentcol=&(palette[index]);
currentcol->red=0;
currentcol->green=0;
currentcol->blue=indexvals1[i];
currentcol->alpha=255;
}
// Reds, following indexvals1 - 1
for(i=0; i<10; i++,index++)
{
currentcol=&(palette[index]);
currentcol->red=indexvals1[i] - 1;
currentcol->green=0;
currentcol->blue=0;
currentcol->alpha=255;
}
// Greens, following indexvals1 - 1
for(i=0; i<10; i++,index++)
{
currentcol=&(palette[index]);
currentcol->red=0;
currentcol->green=indexvals1[i] - 1;
currentcol->blue=0;
currentcol->alpha=255;
}
currentcol+=sizeof(rgb_color);
currentcol->red=0;
currentcol->green=152;
currentcol->blue=51;
index++;
currentcol+=sizeof(rgb_color);
currentcol->red=255;
currentcol->green=255;
currentcol->blue=255;
index++;
for(j=1;j<5;j++)
{
for(i=0;i<6;i++,index++)
{
currentcol=&(palette[index]);
currentcol->red=indexvals2[j];
currentcol->green=255;
currentcol->blue=indexvals2[i];
currentcol->alpha=255;
}
}
for(i=0;i<4;i++,index++)
{
currentcol=&(palette[index]);
currentcol->red=255;
currentcol->green=152;
currentcol->blue=indexvals2[i];
currentcol->alpha=255;
}
currentcol+=sizeof(rgb_color);
currentcol->red=255;
currentcol->green=102;
currentcol->blue=51;
index++;
currentcol+=sizeof(rgb_color);
currentcol->red=255;
currentcol->green=102;
currentcol->blue=0;
index++;
currentcol+=sizeof(rgb_color);
currentcol->red=0;
currentcol->green=102;
currentcol->blue=255;
index++;
currentcol+=sizeof(rgb_color);
currentcol->red=0;
currentcol->green=102;
currentcol->blue=203;
index++;
// Mostly array runs from here on out
for(i=0;i<6;i++,index++)
{
currentcol=&(palette[index]);
currentcol->red=203;
currentcol->green=203;
currentcol->blue=indexvals2[i];
currentcol->alpha=255;
}
for(i=0;i<6;i++,index++)
{
currentcol=&(palette[index]);
currentcol->red=152;
currentcol->green=255;
currentcol->blue=indexvals2[i];
currentcol->alpha=255;
}
for(i=0;i<6;i++,index++)
{
currentcol=&(palette[index]);
currentcol->red=102;
currentcol->green=255;
currentcol->blue=indexvals2[i];
currentcol->alpha=255;
}
for(i=0;i<6;i++,index++)
{
currentcol=&(palette[index]);
currentcol->red=51;
currentcol->green=255;
currentcol->blue=indexvals2[i];
currentcol->alpha=255;
}
for(i=0;i<6;i++,index++)
{
currentcol=&(palette[index]);
currentcol->red=255;
currentcol->green=102;
currentcol->blue=indexvals2[i];
currentcol->alpha=255;
}
currentcol+=sizeof(rgb_color);
currentcol->red=0;
currentcol->green=102;
currentcol->blue=152;
index++;
currentcol+=sizeof(rgb_color);
currentcol->red=0;
currentcol->green=102;
currentcol->blue=102;
index++;
// knocks out 4 assignment loops at once :)
for(j=1;j<5;j++)
{
for(i=0;i<6;i++,index++)
{
currentcol=&(palette[index]);
currentcol->red=indexvals2[j];
currentcol->green=152;
currentcol->blue=indexvals2[i];
currentcol->alpha=255;
}
}
currentcol+=sizeof(rgb_color);
currentcol->red=230;
currentcol->green=134;
currentcol->blue=0;
index++;
for(i=1;i<6;i++,index++)
{
currentcol=&(palette[index]);
currentcol->red=255;
currentcol->green=51;
currentcol->blue=indexvals2[i];
currentcol->alpha=255;
}
currentcol+=sizeof(rgb_color);
currentcol->red=0;
currentcol->green=102;
currentcol->blue=51;
index++;
currentcol+=sizeof(rgb_color);
currentcol->red=0;
currentcol->green=102;
currentcol->blue=0;
index++;
for(j=1;j<5;j++)
{
for(i=0;i<6;i++,index++)
{
currentcol=&(palette[index]);
currentcol->red=indexvals2[j];
currentcol->green=102;
currentcol->blue=indexvals2[i];
currentcol->alpha=255;
}
}
for(i=0;i<6;i++,index++)
{
currentcol=&(palette[index]);
currentcol->red=255;
currentcol->green=0;
currentcol->blue=indexvals2[i];
currentcol->alpha=255;
}
currentcol+=sizeof(rgb_color);
currentcol->red=255;
currentcol->green=175;
currentcol->blue=19;
index++;
currentcol+=sizeof(rgb_color);
currentcol->red=0;
currentcol->green=51;
currentcol->blue=255;
index++;
currentcol+=sizeof(rgb_color);
currentcol->red=0;
currentcol->green=51;
currentcol->blue=203;
index++;
for(j=1;j<5;j++)
{
for(i=0;i<6;i++,index++)
{
currentcol=&(palette[index]);
currentcol->red=indexvals2[j];
currentcol->green=51;
currentcol->blue=indexvals2[i];
currentcol->alpha=255;
}
}
for(i=3;i>=0;i--,index++)
{
currentcol=&(palette[index]);
currentcol->red=255;
currentcol->green=203;
currentcol->blue=indexvals2[i];
currentcol->alpha=255;
}
for(i=2;i<6;i++,index++)
{
currentcol=&(palette[index]);
currentcol->red=0;
currentcol->green=51;
currentcol->blue=indexvals2[i];
currentcol->alpha=255;
}
for(i=0;i<5;i++,index++)
{
currentcol=&(palette[index]);
currentcol->red=203;
currentcol->green=0;
currentcol->blue=indexvals2[i];
currentcol->alpha=255;
}
currentcol+=sizeof(rgb_color);
currentcol->red=255;
currentcol->green=227;
currentcol->blue=70;
index++;
for(j=2;j<6;j++)
{
for(i=0;i<6;i++,index++)
{
currentcol=&(palette[index]);
currentcol->red=indexvals2[j];
currentcol->green=0;
currentcol->blue=indexvals2[i];
currentcol->alpha=255;
}
}
currentcol+=sizeof(rgb_color);
currentcol->red=255;
currentcol->green=203;
currentcol->blue=51;
index++;
currentcol+=sizeof(rgb_color);
currentcol->red=255;
currentcol->green=203;
currentcol->blue=0;
index++;
for(i=5;i<=0;i--,index++)
{
currentcol=&(palette[index]);
currentcol->red=255;
currentcol->green=255;
currentcol->blue=indexvals2[i];
currentcol->alpha=255;
}
}

View File

@ -0,0 +1,992 @@
/*
ViewDriver:
First, slowest, and easiest driver class in the app_server which is designed
to utilize the BeOS graphics functions to cut out a lot of junk in getting the
drawing infrastructure in this server.
The concept is to have VDView::Draw() draw a bitmap, which is a "frame buffer"
of sorts, utilize a second view to write to it. This cuts out
the most problems with having a crapload of code to get just right without
having to write a bunch of unit tests
Components: 3 classes, VDView, VDWindow, and ViewDriver
ViewDriver - a wrapper class which mostly posts messages to the VDWindow
VDWindow - does most of the work.
VDView - doesn't do all that much except display the rendered bitmap
*/
//#define DEBUG_DRIVER_MODULE
//#define DEBUG_SERVER_EMU
//#define DISABLE_SERVER_EMU
#include <stdio.h>
#include <iostream.h>
#include <Message.h>
#include <Region.h>
#include <Bitmap.h>
#include <OS.h>
#include <GraphicsDefs.h>
#include <Font.h>
#include "PortLink.h"
#include "ServerProtocol.h"
#include "ServerBitmap.h"
#include "ViewDriver.h"
#include "ServerCursor.h"
#include "ServerFont.h"
#include "FontFamily.h"
//#include "DebugTools.h"
#include "LayerData.h"
enum
{
VDWIN_CLEAR=100,
VDWIN_SHOWCURSOR,
VDWIN_HIDECURSOR,
VDWIN_OBSCURECURSOR,
VDWIN_MOVECURSOR,
VDWIN_SETCURSOR,
};
ViewDriver *viewdriver_global;
#ifdef DEBUG_DRIVER_MODULE
void DumpLayerData(LayerData *ld)
{
if(ld)
{
printf("Layer Data: \n");
printf("\tPen Size: %f\n"
"\tPen Location: (%f,%f)\n"
"\tDraw Mode: %d\n"
"\tScale: %f\n",
ld->pensize,
ld->penlocation.x, ld->penlocation.y,
ld->draw_mode,
ld->scale);
ld->highcolor.PrintToStream();
ld->lowcolor.PrintToStream();
}
else
{
printf("Layer Data: NULL\n");
}
}
#endif
VDView::VDView(BRect bounds)
: BView(bounds,"viewdriver_view",B_FOLLOW_ALL, B_WILL_DRAW)
{
SetViewColor(B_TRANSPARENT_32_BIT);
viewbmp=new BBitmap(bounds,B_RGB32,true);
// This link for sending mouse messages to the OBAppServer.
// This is only to take the place of the Input Server. I suppose I could write
// an addon filter to be more like the Input Server, but then I wouldn't be working
// on this thing! :P
serverlink=new PortLink(find_port(SERVER_INPUT_PORT));
#ifdef DEBUG_DRIVER_MODULE
printf("VDView: app_server input port: %ld\n",serverlink->GetPort());
#endif
// Create a cursor which isn't just a box
cursor=new BBitmap(BRect(0,0,20,20),B_RGBA32,true);
BView *v=new BView(cursor->Bounds(),"v", B_FOLLOW_NONE, B_WILL_DRAW);
hide_cursor=0;
cursor->Lock();
cursor->AddChild(v);
v->SetHighColor(255,255,255,0);
v->FillRect(cursor->Bounds());
v->SetHighColor(255,0,0,255);
v->FillTriangle(cursor->Bounds().LeftTop(),cursor->Bounds().RightTop(),cursor->Bounds().LeftBottom());
cursor->RemoveChild(v);
cursor->Unlock();
cursorframe=cursor->Bounds();
oldcursorframe=cursor->Bounds();
}
VDView::~VDView(void)
{
delete serverlink;
delete viewbmp;
delete cursor;
}
void VDView::AttachedToWindow(void)
{
}
void VDView::Draw(BRect rect)
{
if(viewbmp)
{
DrawBitmapAsync(viewbmp,oldcursorframe,oldcursorframe);
DrawBitmapAsync(viewbmp,rect,rect);
if(hide_cursor==0 && obscure_cursor==false)
{
SetDrawingMode(B_OP_ALPHA);
DrawBitmapAsync(cursor,cursor->Bounds(),cursorframe);
SetDrawingMode(B_OP_COPY);
}
Sync();
}
}
// These functions emulate the Input Server by sending the *exact* same kind of messages
// to the server's port. Being we're using a regular window, it would make little sense
// to do anything else.
void VDView::MouseDown(BPoint pt)
{
#ifdef DEBUG_SERVER_EMU
printf("ViewDriver::MouseDown\n");
#endif
// Attach data:
// 1) int64 - time of mouse click
// 2) float - x coordinate of mouse click
// 3) float - y coordinate of mouse click
// 4) int32 - modifier keys down
// 5) int32 - buttons down
// 6) int32 - clicks
#ifndef DISABLE_SERVER_EMU
BPoint p;
uint32 buttons,
mod=modifiers(),
clicks=1; // can't get the # of clicks without a *lot* of extra work :(
int64 time=(int64)real_time_clock();
GetMouse(&p,&buttons);
serverlink->SetOpCode(B_MOUSE_DOWN);
serverlink->Attach(&time, sizeof(int64));
serverlink->Attach(&pt.x,sizeof(float));
serverlink->Attach(&pt.y,sizeof(float));
serverlink->Attach(&mod, sizeof(uint32));
serverlink->Attach(&buttons, sizeof(uint32));
serverlink->Attach(&clicks, sizeof(uint32));
serverlink->Flush();
#endif
}
void VDView::MouseMoved(BPoint pt, uint32 transit, const BMessage *msg)
{
// Attach data:
// 1) int64 - time of mouse click
// 2) float - x coordinate of mouse click
// 3) float - y coordinate of mouse click
// 4) int32 - buttons down
#ifndef DISABLE_SERVER_EMU
BPoint p;
uint32 buttons;
int64 time=(int64)real_time_clock();
serverlink->SetOpCode(B_MOUSE_MOVED);
serverlink->Attach(&time,sizeof(int64));
serverlink->Attach(&pt.x,sizeof(float));
serverlink->Attach(&pt.y,sizeof(float));
GetMouse(&p,&buttons);
serverlink->Attach(&buttons,sizeof(int32));
serverlink->Flush();
#endif
}
void VDView::MouseUp(BPoint pt)
{
#ifdef DEBUG_SERVER_EMU
printf("ViewDriver::MouseUp\n");
#endif
// Attach data:
// 1) int64 - time of mouse click
// 2) float - x coordinate of mouse click
// 3) float - y coordinate of mouse click
// 4) int32 - modifier keys down
#ifndef DISABLE_SERVER_EMU
BPoint p;
uint32 buttons,
mod=modifiers();
int64 time=(int64)real_time_clock();
GetMouse(&p,&buttons);
serverlink->SetOpCode(B_MOUSE_UP);
serverlink->Attach(&time, sizeof(int64));
serverlink->Attach(&pt.x,sizeof(float));
serverlink->Attach(&pt.y,sizeof(float));
serverlink->Attach(&mod, sizeof(uint32));
serverlink->Flush();
#endif
}
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
VDWindow::VDWindow(void)
: BWindow(BRect(100,60,740,540),"OBOS App Server, P7",B_TITLED_WINDOW,
B_NOT_ZOOMABLE | B_NOT_RESIZABLE)
{
view=new VDView(Bounds());
AddChild(view);
}
VDWindow::~VDWindow(void)
{
}
void VDWindow::MessageReceived(BMessage *msg)
{
switch(msg->what)
{
case VDWIN_SHOWCURSOR:
{
if(view->hide_cursor>0)
{
view->hide_cursor--;
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: ShowCursor() - still hidden\n");
#endif
}
if(view->hide_cursor==0)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: ShowCursor() - cursor shown\n");
#endif
view->Invalidate(view->cursorframe);
}
break;
}
case VDWIN_HIDECURSOR:
{
view->hide_cursor++;
if(view->hide_cursor==1)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: HideCursor() - cursor was hidden\n");
#endif
view->Invalidate(view->cursorframe);
}
else
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: HideCursor()\n");
#endif
}
break;
}
case VDWIN_OBSCURECURSOR:
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: ObscureCursor()\n");
#endif
view->obscure_cursor=true;
view->Invalidate(view->cursorframe);
break;
}
case VDWIN_MOVECURSOR:
{
float x,y;
msg->FindFloat("x",&x);
msg->FindFloat("y",&y);
// this was changed because an extra message was
// sent even though the mouse was never moved
if(view->cursorframe.left!=x || view->cursorframe.top!=y)
{
if(view->obscure_cursor)
view->obscure_cursor=false;
view->oldcursorframe=view->cursorframe;
view->cursorframe.OffsetTo(x,y);
}
if(view->hide_cursor==0)
view->Invalidate(view->oldcursorframe);
break;
}
case VDWIN_SETCURSOR:
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: SetCursor()\n");
#endif
ServerCursor *cdata;
msg->FindPointer("SCursor",(void**)&cdata);
if(cdata!=NULL)
{
BBitmap *bmp=new BBitmap(cdata->Bounds(), B_RGBA32);
// Copy the server bitmap in the cursor to a BBitmap
uint8 *sbmppos=(uint8*)cdata->Buffer(),
*bbmppos=(uint8*)bmp->Bits();
int32 bytes=cdata->BytesPerLine(),
bbytes=bmp->BytesPerRow();
for(int i=0;i<cdata->Height();i++)
memcpy(bbmppos+(i*bbytes), sbmppos+(i*bytes), bytes);
// Replace the bitmap
delete view->cursor;
view->cursor=bmp;
view->Invalidate(view->cursorframe);
break;
}
break;
}
default:
BWindow::MessageReceived(msg);
break;
}
}
bool VDWindow::QuitRequested(void)
{
port_id serverport=find_port(SERVER_PORT_NAME);
if(serverport!=B_NAME_NOT_FOUND)
write_port(serverport,B_QUIT_REQUESTED,NULL,0);
return true;
}
void VDWindow::WindowActivated(bool active)
{
// This is just to hide the regular system cursor so we can see our own
if(active)
be_app->HideCursor();
else
be_app->ShowCursor();
}
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
ViewDriver::ViewDriver(void)
{
viewdriver_global=this;
screenwin=new VDWindow();
framebuffer=screenwin->view->viewbmp;
serverlink=screenwin->view->serverlink;
hide_cursor=0;
}
ViewDriver::~ViewDriver(void)
{
if(is_initialized)
{
screenwin->Lock();
screenwin->Quit();
screenwin=NULL;
}
}
bool ViewDriver::Initialize(void)
{
Lock();
drawview=new BView(framebuffer->Bounds(),"drawview",B_FOLLOW_ALL, B_WILL_DRAW);
framebuffer->AddChild(drawview);
hide_cursor=0;
obscure_cursor=false;
is_initialized=true;
// We can afford to call the above functions without locking
// because the window is locked until Show() is first called
screenwin->Show();
Unlock();
return true;
}
void ViewDriver::Shutdown(void)
{
Lock();
is_initialized=false;
Unlock();
}
void ViewDriver::SetMode(int32 space)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: SetMode(%ld)\n",space);
#endif
screenwin->Lock();
int16 w=640,h=480;
color_space s;
switch(space)
{
case B_32_BIT_800x600:
case B_16_BIT_800x600:
case B_8_BIT_800x600:
{
w=800; h=600;
break;
}
case B_32_BIT_1024x768:
case B_16_BIT_1024x768:
case B_8_BIT_1024x768:
{
w=1024; h=768;
break;
}
default:
break;
}
screenwin->ResizeTo(w-1,h-1);
switch(space)
{
case B_32_BIT_640x480:
case B_32_BIT_800x600:
case B_32_BIT_1024x768:
s=B_RGBA32;
break;
case B_16_BIT_640x480:
case B_16_BIT_800x600:
case B_16_BIT_1024x768:
s=B_RGBA15;
break;
case B_8_BIT_640x480:
case B_8_BIT_800x600:
case B_8_BIT_1024x768:
s=B_CMAP8;
break;
default:
break;
}
delete framebuffer;
screenwin->view->viewbmp=new BBitmap(BRect(0,0,w-1,h-1),s,true);
framebuffer=screenwin->view->viewbmp;
drawview=new BView(framebuffer->Bounds(),"drawview",B_FOLLOW_ALL, B_WILL_DRAW);
framebuffer->AddChild(drawview);
framebuffer->Lock();
drawview->SetHighColor(80,85,152);
drawview->FillRect(drawview->Bounds());
drawview->Sync();
framebuffer->Unlock();
screenwin->view->Invalidate();
screenwin->Unlock();
}
void ViewDriver::CopyBits(BRect src, BRect dest)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: CopyBits()\n"); src.PrintToStream(); dest.PrintToStream();
#endif
screenwin->Lock();
framebuffer->Lock();
drawview->CopyBits(src,dest);
drawview->Sync();
screenwin->view->Invalidate(dest);
framebuffer->Unlock();
screenwin->Unlock();
}
void ViewDriver::DrawBitmap(ServerBitmap *bitmap, BRect src, BRect dest)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: DrawBitmap unimplemented()\n");
#endif
}
void ViewDriver::DrawChar(char c, BPoint pt, LayerData *d)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: DrawChar(%c, BPoint(%f,%f))\n",c,pt.x,pt.y);
#endif
char str[2];
str[0]=c;
str[1]='\0';
DrawString(str, 1, pt, d);
}
void ViewDriver::DrawString(const char *string, int32 length, BPoint pt, LayerData *d, escapement_delta *delta=NULL)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: DrawString(\"%s\",%ld,BPoint(%f,%f))\n",string,length,pt.x,pt.y);
#endif
if(!d)
return;
BRect r;
screenwin->Lock();
framebuffer->Lock();
SetLayerData(d,true); // set all layer data and additionally set the font-related data
drawview->DrawString(string,length,pt,delta);
drawview->Sync();
// calculate the invalid rectangle
font_height fh;
BFont font;
drawview->GetFont(&font);
drawview->GetFontHeight(&fh);
r.left=pt.x;
r.right=pt.x+font.StringWidth(string);
r.top=pt.y-fh.ascent;
r.bottom=pt.y+fh.descent;
screenwin->view->Invalidate(r);
framebuffer->Unlock();
screenwin->Unlock();
}
/*
bool ViewDriver::DumpToFile(const char *path)
{
return false;
}
*/
void ViewDriver::FillArc(BRect r, float angle, float span, LayerData *d, int8 *pat)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: FillArc()\n");
#endif
if(!pat || !d)
return;
screenwin->Lock();
framebuffer->Lock();
SetLayerData(d);
drawview->FillArc(r,angle,span,*((pattern*)pat));
drawview->Sync();
screenwin->view->Invalidate(r);
framebuffer->Unlock();
screenwin->Unlock();
}
void ViewDriver::FillBezier(BPoint *pts, LayerData *d, int8 *pat)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: FillBezier()\n");
#endif
if(!pat || !pts)
return;
screenwin->Lock();
framebuffer->Lock();
SetLayerData(d);
drawview->FillBezier(pts,*((pattern*)pat));
drawview->Sync();
// Invalidate the whole view until I get around to adding in the invalid rect calc code
screenwin->view->Invalidate();
framebuffer->Unlock();
screenwin->Unlock();
}
void ViewDriver::FillEllipse(BRect r, LayerData *d, int8 *pat)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: FillEllipse()\n");
#endif
if(!pat || !d)
return;
screenwin->Lock();
framebuffer->Lock();
SetLayerData(d);
drawview->FillEllipse(r,*((pattern*)pat));
drawview->Sync();
screenwin->view->Invalidate(r);
framebuffer->Unlock();
screenwin->Unlock();
}
void ViewDriver::FillPolygon(BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, int8 *pat)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: FillPolygon unimplemented\n");
#endif
if(!pat || !ptlist)
return;
}
void ViewDriver::FillRect(BRect r, LayerData *d, int8 *pat)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: FillRect()\n");
#endif
if(!pat || !d)
return;
screenwin->Lock();
framebuffer->Lock();
SetLayerData(d);
drawview->FillRect(r,*((pattern*)pat));
drawview->Sync();
screenwin->view->Invalidate(r);
framebuffer->Unlock();
screenwin->Unlock();
}
void ViewDriver::FillRoundRect(BRect r, float xrad, float yrad, LayerData *d, int8 *pat)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: FillRoundRect()\n");
#endif
if(!pat || !d)
return;
screenwin->Lock();
framebuffer->Lock();
SetLayerData(d);
drawview->FillRoundRect(r,xrad,yrad,*((pattern*)pat));
drawview->Sync();
screenwin->view->Invalidate(r);
framebuffer->Unlock();
screenwin->Unlock();
}
void ViewDriver::FillTriangle(BPoint *pts, BRect r, LayerData *d, int8 *pat)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: FillTriangle()\n");
#endif
if(!pat || !pts)
return;
screenwin->Lock();
framebuffer->Lock();
BPoint first=pts[0],second=pts[1],third=pts[2];
SetLayerData(d);
drawview->FillTriangle(first,second,third,r,*((pattern*)pat));
drawview->Sync();
screenwin->view->Invalidate(r);
framebuffer->Unlock();
screenwin->Unlock();
}
void ViewDriver::HideCursor(void)
{
screenwin->Lock();
Lock();
hide_cursor++;
screenwin->PostMessage(VDWIN_HIDECURSOR);
Unlock();
screenwin->Unlock();
}
void ViewDriver::InvertRect(BRect r)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: InvertRect()\n");
#endif
screenwin->Lock();
framebuffer->Lock();
drawview->InvertRect(r);
drawview->Sync();
screenwin->view->Invalidate(r);
framebuffer->Unlock();
screenwin->Unlock();
}
bool ViewDriver::IsCursorHidden(void)
{
screenwin->Lock();
bool value=(hide_cursor>0)?true:false;
screenwin->Unlock();
return value;
}
void ViewDriver::ObscureCursor(void)
{
screenwin->Lock();
screenwin->PostMessage(VDWIN_OBSCURECURSOR);
screenwin->Unlock();
}
void ViewDriver::MoveCursorTo(float x, float y)
{
screenwin->Lock();
BMessage *msg=new BMessage(VDWIN_MOVECURSOR);
msg->AddFloat("x",x);
msg->AddFloat("y",y);
screenwin->PostMessage(msg);
screenwin->Unlock();
}
void ViewDriver::SetCursor(ServerCursor *cursor)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: SetCursor(%p)\n",cursor);
#endif
if(cursor!=NULL)
{
screenwin->Lock();
BBitmap *bmp=new BBitmap(cursor->Bounds(),B_RGBA32);
// Copy the server bitmap in the cursor to a BBitmap
uint8 *sbmppos=(uint8*)cursor->Buffer(),
*bbmppos=(uint8*)bmp->Bits();
int32 bytes=cursor->BytesPerLine(),
bbytes=bmp->BytesPerRow();
for(int i=0;i<cursor->Height();i++)
memcpy(bbmppos+(i*bbytes), sbmppos+(i*bytes), bytes);
// Replace the bitmap
delete screenwin->view->cursor;
screenwin->view->cursor=bmp;
screenwin->view->Invalidate(screenwin->view->cursorframe);
screenwin->Unlock();
}
}
void ViewDriver::ShowCursor(void)
{
screenwin->Lock();
if(hide_cursor>0)
{
hide_cursor--;
screenwin->PostMessage(VDWIN_SHOWCURSOR);
}
screenwin->Unlock();
}
void ViewDriver::StrokeArc(BRect r, float angle, float span, LayerData *d, int8 *pat)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: StrokeArc()\n");
#endif
if(!pat || !d)
return;
screenwin->Lock();
framebuffer->Lock();
SetLayerData(d);
drawview->StrokeArc(r,angle,span,*((pattern*)pat));
drawview->Sync();
screenwin->view->Invalidate(r);
framebuffer->Unlock();
screenwin->Unlock();
}
void ViewDriver::StrokeBezier(BPoint *pts, LayerData *d, int8 *pat)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: StrokeBezier()\n");
#endif
if(!pat || !pts)
return;
screenwin->Lock();
framebuffer->Lock();
SetLayerData(d);
drawview->StrokeBezier(pts,*((pattern*)pat));
drawview->Sync();
// Invalidate the whole view until I get around to adding in the invalid rect calc code
screenwin->view->Invalidate();
framebuffer->Unlock();
screenwin->Unlock();
}
void ViewDriver::StrokeEllipse(BRect r, LayerData *d, int8 *pat)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: StrokeEllipse()\n");
#endif
if(!pat || !d)
return;
screenwin->Lock();
framebuffer->Lock();
SetLayerData(d);
drawview->StrokeEllipse(r,*((pattern*)pat));
drawview->Sync();
screenwin->view->Invalidate(r);
framebuffer->Unlock();
screenwin->Unlock();
}
void ViewDriver::StrokeLine(BPoint start, BPoint end, LayerData *d, int8 *pat)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: StrokeLine()\n");
#endif
if(!pat || !d)
return;
screenwin->Lock();
framebuffer->Lock();
SetLayerData(d);
drawview->StrokeLine(start,end,*((pattern*)pat));
drawview->Sync();
screenwin->view->Invalidate(BRect(start,end));
framebuffer->Unlock();
screenwin->Unlock();
}
void ViewDriver::StrokeLineArray(BPoint *pts, int32 numlines, RGBColor *colors, LayerData *d)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: StrokeLineArray unimplemented\n");
#endif
}
void ViewDriver::StrokePolygon(BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, int8 *pat, bool is_closed=true)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: StrokePolygon()\n");
#endif
if(!pat || !ptlist)
return;
screenwin->Lock();
framebuffer->Lock();
BRegion invalid;
SetLayerData(d);
drawview->BeginLineArray(numpts+2);
for(int i=1;i<numpts;i++)
{
drawview->AddLine(ptlist[i-1],ptlist[i],d->highcolor.GetColor32());
invalid.Include(BRect(ptlist[i-1],ptlist[i]));
}
if(is_closed)
{
drawview->AddLine(ptlist[numpts-1],ptlist[0],d->highcolor.GetColor32());
invalid.Include(BRect(ptlist[numpts-1],ptlist[0]));
}
drawview->EndLineArray();
drawview->Sync();
screenwin->view->Invalidate(invalid.Frame());
framebuffer->Unlock();
screenwin->Unlock();
}
void ViewDriver::StrokeRect(BRect r, LayerData *d, int8 *pat)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: StrokeRect()\n");
#endif
if(!pat || !d)
return;
screenwin->Lock();
framebuffer->Lock();
SetLayerData(d);
drawview->StrokeRect(r,*((pattern*)pat));
drawview->Sync();
screenwin->view->Invalidate(r);
framebuffer->Unlock();
screenwin->Unlock();
}
void ViewDriver::StrokeRoundRect(BRect r, float xrad, float yrad, LayerData *d, int8 *pat)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: StrokeRoundRect()\n");
#endif
if(!pat || !d)
return;
screenwin->Lock();
framebuffer->Lock();
SetLayerData(d);
drawview->StrokeRoundRect(r,xrad,yrad,*((pattern*)pat));
drawview->Sync();
screenwin->view->Invalidate(r);
framebuffer->Unlock();
screenwin->Unlock();
}
void ViewDriver::StrokeTriangle(BPoint *pts, BRect r, LayerData *d, int8 *pat)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver:: StrokeTriangle()\n");
#endif
if(!pat || !pts || !d)
return;
screenwin->Lock();
framebuffer->Lock();
BPoint first=pts[0],second=pts[1],third=pts[2];
SetLayerData(d);
drawview->StrokeTriangle(first,second,third,r,*((pattern*)pat));
drawview->Sync();
screenwin->view->Invalidate(r);
framebuffer->Unlock();
screenwin->Unlock();
}
void ViewDriver::SetLayerData(LayerData *d, bool set_font_data=false)
{
if(!d)
return;
drawview->SetPenSize(d->pensize);
drawview->SetDrawingMode(d->draw_mode);
drawview->SetHighColor(d->highcolor.GetColor32());
drawview->SetLowColor(d->lowcolor.GetColor32());
drawview->SetScale(d->scale);
drawview->MovePenTo(d->penlocation);
if(set_font_data)
{
BFont font;
ServerFont *sf=d->font;
if(!sf)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver::SetLayerData was passed a NULL ServerFont\n");
#endif
return;
}
FontStyle *style=d->font->Style();
if(!style)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver::SetLayerData font had a NULL style\n");
#endif
return;
}
FontFamily *family=(FontFamily *)style->Family();
if(!family)
{
#ifdef DEBUG_DRIVER_MODULE
printf("ViewDriver::SetLayerData font had a NULL family\n");
#endif
}
font.SetFamilyAndStyle((font_family)family->GetName(),style->Style());
font.SetFlags(sf->Flags());
font.SetEncoding(sf->Encoding());
font.SetSize(sf->Size());
font.SetRotation(sf->Rotation());
font.SetShear(sf->Shear());
font.SetSpacing(sf->Spacing());
drawview->SetFont(&font);
}
}

View File

@ -0,0 +1,120 @@
#ifndef _VIEWDRIVER_H_
#define _VIEWDRIVER_H_
#include <Application.h>
#include <Window.h>
#include <View.h>
#include <GraphicsCard.h>
#include <GraphicsDefs.h> // for pattern struct
#include <Cursor.h>
#include <Message.h>
#include <Region.h>
#include <Font.h>
#include "DisplayDriver.h"
class BBitmap;
class PortLink;
class VDWindow;
class ServerCursor;
class LayerData;
class VDView : public BView
{
public:
VDView(BRect bounds);
~VDView(void);
void AttachedToWindow(void);
void Draw(BRect rect);
void MouseDown(BPoint pt);
void MouseMoved(BPoint pt, uint32 transit, const BMessage *msg);
void MouseUp(BPoint pt);
BBitmap *viewbmp;
PortLink *serverlink;
int hide_cursor;
BBitmap *cursor;
BRect cursorframe, oldcursorframe;
bool obscure_cursor;
};
class VDWindow : public BWindow
{
public:
VDWindow(void);
~VDWindow(void);
void MessageReceived(BMessage *msg);
bool QuitRequested(void);
void WindowActivated(bool active);
VDView *view;
};
class ViewDriver : public DisplayDriver
{
public:
ViewDriver(void);
~ViewDriver(void);
bool Initialize(void); // Sets the driver
void Shutdown(void); // You never know when you'll need this
// Drawing functions
void CopyBits(BRect src, BRect dest);
void DrawBitmap(ServerBitmap *bmp, BRect src, BRect dest);
void DrawChar(char c, BPoint pt, LayerData *d);
// virtual void DrawPicture(SPicture *pic, BPoint pt);
void DrawString(const char *string, int32 length, BPoint pt, LayerData *d, escapement_delta *delta=NULL);
void FillArc(BRect r, float angle, float span, LayerData *d, int8 *pat);
void FillBezier(BPoint *pts, LayerData *d, int8 *pat);
void FillEllipse(BRect r, LayerData *d, int8 *pat);
void FillPolygon(BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, int8 *pat);
void FillRect(BRect r, LayerData *d, int8 *pat);
void FillRoundRect(BRect r, float xrad, float yrad, LayerData *d, int8 *pat);
// void FillShape(SShape *sh, LayerData *d, int8 *pat);
void FillTriangle(BPoint *pts, BRect r, LayerData *d, int8 *pat);
void HideCursor(void);
void InvertRect(BRect r);
bool IsCursorHidden(void);
void MoveCursorTo(float x, float y);
// void MovePenTo(BPoint pt);
void ObscureCursor(void);
// BPoint PenPosition(void);
// float PenSize(void);
void SetCursor(ServerCursor *cursor);
// drawing_mode GetDrawingMode(void);
// void SetDrawingMode(drawing_mode mode);
void ShowCursor(void);
void StrokeArc(BRect r, float angle, float span, LayerData *d, int8 *pat);
void StrokeBezier(BPoint *pts, LayerData *d, int8 *pat);
void StrokeEllipse(BRect r, LayerData *d, int8 *pat);
void StrokeLine(BPoint start, BPoint end, LayerData *d, int8 *pat);
void StrokeLineArray(BPoint *pts, int32 numlines, RGBColor *colors, LayerData *d);
void StrokePolygon(BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, int8 *pat, bool is_closed=true);
void StrokeRect(BRect r, LayerData *d, int8 *pat);
void StrokeRoundRect(BRect r, float xrad, float yrad, LayerData *d, int8 *pat);
// void StrokeShape(SShape *sh, LayerData *d, int8 *pat);
void StrokeTriangle(BPoint *pts, BRect r, LayerData *d, int8 *pat);
void SetMode(int32 mode);
// bool DumpToFile(const char *path);
VDWindow *screenwin;
protected:
void SetLayerData(LayerData *d, bool set_font_data=false);
int hide_cursor;
bool obscure_cursor;
BBitmap *framebuffer;
BView *drawview;
BRegion laregion;
PortLink *serverlink;
// drawing_mode drawmode;
rgb_color highcolor,lowcolor;
bool is_initialized;
};
#endif

View File

@ -0,0 +1,379 @@
#include <String.h>
#include <Locker.h>
#include <Region.h>
#include <Debug.h>
#include "View.h" // for mouse button defines
#include "ServerWindow.h"
#include "WindowBorder.h"
#include "Decorator.h"
#include "Desktop.h"
#define DEBUG_WINBORDER
#ifdef DEBUG_WINBORDER
#include <stdio.h>
#endif
bool is_moving_window=false;
bool is_resizing_window=false;
extern ServerWindow *active_serverwindow;
WindowBorder::WindowBorder(ServerWindow *win, const char *bordertitle)
: Layer((win==NULL)?BRect(0,0,1,1):win->frame,
(win==NULL)?NULL:win->title->String())
{
#ifdef DEBUG_WINBORDER
printf("WindowBorder()\n");
#endif
mbuttons=0;
swin=win;
mousepos.Set(0,0);
update=false;
title=new BString(bordertitle);
hresizewin=false;
vresizewin=false;
}
WindowBorder::~WindowBorder(void)
{
#ifdef DEBUG_WINBORDER
printf("~WindowBorder()\n");
#endif
delete title;
}
void WindowBorder::MouseDown(BPoint pt, int32 buttons, int32 modifiers)
{
mbuttons=buttons;
kmodifiers=modifiers;
click_type click=decor->Clicked(pt, mbuttons, kmodifiers);
mousepos=pt;
switch(click)
{
case CLICK_MOVETOBACK:
{
MoveToBack();
break;
}
case CLICK_MOVETOFRONT:
{
MoveToFront();
break;
}
case CLICK_CLOSE:
{
#ifdef DEBUG_WINBORDER
printf("WindowBorder(): SetClose\n");
#endif
decor->SetClose(true);
decor->Draw();
break;
}
case CLICK_ZOOM:
{
#ifdef DEBUG_WINBORDER
printf("WindowBorder(): SetZoom\n");
#endif
decor->SetZoom(true);
decor->Draw();
break;
}
case CLICK_MINIMIZE:
{
#ifdef DEBUG_WINBORDER
printf("WindowBorder(): SetMinimize\n");
#endif
decor->SetMinimize(true);
decor->Draw();
break;
}
case CLICK_DRAG:
{
#ifdef DEBUG_WINBORDER
printf("WindowBorder(): Click Tab\n");
#endif
if(buttons==B_PRIMARY_MOUSE_BUTTON)
{
is_moving_window=true;
}
if(buttons==B_SECONDARY_MOUSE_BUTTON)
MoveToBack();
break;
}
case CLICK_RESIZE:
{
#ifdef DEBUG_WINBORDER
printf("WindowBorder(): Click Resize\n");
#endif
if(buttons==B_PRIMARY_MOUSE_BUTTON)
{
is_resizing_window=true;
}
break;
}
case CLICK_NONE:
{
#ifdef DEBUG_WINBORDER
printf("WindowBorder(): Click None\n");
#endif
break;
}
default:
{
#ifdef DEBUG_WINBORDER
printf("WindowBorder()::MouseDown: Undefined click type\n");
#endif
break;
}
}
if(click!=CLICK_NONE)
ActivateWindow(swin);
}
void WindowBorder::MouseMoved(BPoint pt, int32 buttons, int32 modifiers)
{
mbuttons=buttons;
kmodifiers=modifiers;
click_type click=decor->Clicked(pt, mbuttons, kmodifiers);
if(click!=CLICK_CLOSE && decor->GetClose())
{
decor->SetClose(false);
decor->Draw();
}
if(click!=CLICK_ZOOM && decor->GetZoom())
{
decor->SetZoom(false);
decor->Draw();
}
if(click!=CLICK_MINIMIZE && decor->GetMinimize())
{
decor->SetMinimize(false);
decor->Draw();
}
if(is_moving_window==true)
{
float dx=pt.x-mousepos.x,
dy=pt.y-mousepos.y;
if(dx!=0 || dy!=0)
{
BRect oldmoveframe=swin->frame;
clientframe.OffsetBy(pt);
swin->Lock();
swin->frame.OffsetBy(dx,dy);
swin->Unlock();
layerlock->Lock();
// InvalidateLowerSiblings(oldmoveframe);
parent->Invalidate(oldmoveframe);
MoveBy(dx,dy);
parent->RequestDraw();
decor->MoveBy(BPoint(dx, dy));
decor->Draw();
layerlock->Unlock();
}
}
if(is_resizing_window==true)
{
float dx=pt.x-mousepos.x,
dy=pt.y-mousepos.y;
if(dx!=0 || dy!=0)
{
clientframe.right+=dx;
clientframe.bottom+=dy;
swin->Lock();
swin->frame.right+=dx;
swin->frame.bottom+=dy;
swin->Unlock();
layerlock->Lock();
ResizeBy(dx,dy);
parent->RequestDraw();
layerlock->Unlock();
decor->ResizeBy(dx,dy);
decor->Draw();
}
}
mousepos=pt;
}
void WindowBorder::MouseUp(BPoint pt, int32 buttons, int32 modifiers)
{
// mbuttons&= ~buttons;
mbuttons=buttons;
kmodifiers=modifiers;
is_moving_window=false;
is_resizing_window=false;
click_type click=decor->Clicked(pt, mbuttons, kmodifiers);
switch(click)
{
case CLICK_CLOSE:
{
decor->SetClose(false);
decor->Draw();
// call close window stuff here
break;
}
case CLICK_ZOOM:
{
decor->SetZoom(false);
decor->Draw();
// call zoom stuff here
break;
}
case CLICK_MINIMIZE:
{
decor->SetMinimize(false);
decor->Draw();
// call minimize stuff here
}
default:
{
break;
}
}
}
void WindowBorder::Draw(BRect update_rect)
{
#ifdef DEBUG_WINBORDER
printf("WindowBorder()::Draw():"); update_rect.PrintToStream();
#endif
if(update && visible!=NULL)
is_updating=true;
decor->Draw(update_rect);
if(update && visible!=NULL)
is_updating=false;
}
void WindowBorder::SetDecorator(Decorator *newdecor)
{
// AtheOS kills the decorator here. However, the decor
// under OBOS doesn't belong to the border - it belongs to the
// ServerWindow, so the ServerWindow will handle all (de)allocation
// tasks. We just need to update the pointer.
#ifdef DEBUG_WINBORDER
printf("WindowBorder::SetDecorator(%p)\n",newdecor);
#endif
if(newdecor)
{
decor=newdecor;
// if(visible)
// delete visible;
// visible=decor->GetFootprint();
}
}
ServerWindow *WindowBorder::Window(void) const
{
return swin;
}
void WindowBorder::RequestDraw(void)
{
//printf("Layer %s::RequestDraw\n",name->String());
if(invalid)
{
//printf("drew something\n");
// for(int32 i=0; i<invalid->CountRects();i++)
// decor->Draw(ConvertToTop(invalid->RectAt(i)));
decor->Draw();
delete invalid;
invalid=NULL;
is_dirty=false;
}
}
void WindowBorder::InvalidateLowerSiblings(BRect r)
{
// this is used to update the other windows when a window border
// is moved or resized.
Layer *lay;
BRect toprect=ConvertToTop(r);
for(lay=uppersibling;lay!=NULL;lay=lay->uppersibling)
{
lay->Invalidate(toprect);
lay->RequestDraw();
}
}
void WindowBorder::MoveToBack(void)
{
#ifdef DEBUG_WINBORDER
printf("WindowBorder(): MoveToBack\n");
#endif
Layer *temp=NULL;
if(uppersibling)
temp=uppersibling;
// Move the window to the back (the top of the tree)
Layer *top=GetRootLayer();
ASSERT(top!=NULL);
layerlock->Lock();
top->RemoveChild(this);
top->AddChild(this);
level=1;
swin->SetFocus(false);
decor->SetFocus(false);
decor->Draw();
if(temp)
ActivateWindow(uppersibling->serverwin);
layerlock->Unlock();
parent->RebuildRegions(true);
}
void WindowBorder::MoveToFront(void)
{
#ifdef DEBUG_WINBORDER
printf("MoveToFront: \n");
#endif
// Move the window to the front by making it the bottom
// child of the root layer
Layer *top=GetRootLayer();
layerlock->Lock();
top->RemoveChild(this);
// Make this the bottom child of the parent layer. Can't use
// AddChild(), so we'll manipulate the pointers directly. Remember,
// we need to change pointers for 4 layers - the parent, the
// uppersibling (if any), the lowersibling, and the layer in question
// temporary placeholder while we exchange the data
Layer *templayer;
// tweak parent
templayer=top->bottomchild;
top->bottomchild=this;
// Tweak this layer
parent=top;
uppersibling=templayer;
uppersibling->lowersibling=this;
lowersibling=NULL;
layerlock->Unlock();
is_moving_window=true;
parent->RebuildRegions(true);
}

View File

@ -0,0 +1,40 @@
#ifndef _WINBORDER_H_
#define _WINBORDER_H_
#include <Rect.h>
#include <String.h>
#include "Layer.h"
class ServerWindow;
class Decorator;
class WindowBorder : public Layer
{
public:
WindowBorder(ServerWindow *win, const char *bordertitle);
~WindowBorder(void);
void MouseDown(BPoint pt, int32 buttons, int32 modifiers);
void MouseMoved(BPoint pt, int32 buttons, int32 modifiers);
void MouseUp(BPoint pt, int32 buttons, int32 modifiers);
void Draw(BRect update);
void SystemColorsUpdated(void);
void SetDecorator(Decorator *newdecor);
ServerWindow *Window(void) const;
void RequestDraw(void);
void MoveToBack(void);
void MoveToFront(void);
void InvalidateLowerSiblings(BRect r);
ServerWindow *swin;
BString *title;
Decorator *decor;
int32 flags;
BRect frame, clientframe;
int32 mbuttons,kmodifiers;
BPoint mousepos;
bool update;
bool hresizewin,vresizewin;
};
extern bool is_moving_window, is_resizing_window;
#endif

View File

@ -0,0 +1,367 @@
/*
ClientFontList.cpp:
Maintainer object for the list of font families and styles which is
kept on the client side.
*/
#include <File.h>
#include <Message.h>
#include <String.h>
#include <stdio.h>
#include <string.h>
#include "PortLink.h"
#include "ServerProtocol.h"
#include "ClientFontList.h"
#define DEBUG_CLIENT_FONT_LIST
class FontListFamily
{
public:
FontListFamily(void);
~FontListFamily(void);
BString name;
BList *styles;
int32 flags;
};
FontListFamily::FontListFamily(void)
{
styles=new BList(0);
flags=0;
}
FontListFamily::~FontListFamily(void)
{
BString *s;
s=(BString*)styles->RemoveItem(0L);
while(s)
{
delete s;
s=(BString*)styles->RemoveItem(0L);
}
delete styles;
}
ClientFontList::ClientFontList(void)
{
#ifdef DEBUG_CLIENT_FONT_LIST
printf("ClientFontList()\n");
#endif
familylist=new BList(0);
fontlock=create_sem(1,"fontlist_sem");
}
ClientFontList::~ClientFontList(void)
{
#ifdef DEBUG_CLIENT_FONT_LIST
printf("~ClientFontList()\n");
#endif
acquire_sem(fontlock);
font_family *fam;
while(familylist->ItemAt(0L)!=NULL)
{
fam=(font_family *)familylist->RemoveItem(0L);
delete fam;
}
familylist->MakeEmpty();
delete familylist;
delete_sem(fontlock);
}
bool ClientFontList::Update(bool check_only)
{
#ifdef DEBUG_CLIENT_FONT_LIST
printf("ClientFontList::Update(%s) - %s\n", (check_only)?"true":"false",SERVER_FONT_LIST);
#endif
// Open the font list kept in font list
acquire_sem(fontlock);
// We're going to ask the server whether the list has changed
port_id serverport;
serverport=find_port(SERVER_PORT_NAME);
bool needs_update=true;
PortLink *serverlink=new PortLink(serverport);
if(serverport!=B_NAME_NOT_FOUND)
{
status_t stat;
int32 code;
ssize_t buffersize;
serverlink->SetOpCode(QUERY_FONTS_CHANGED);
serverlink->FlushWithReply(&code, &stat, &buffersize);
// Attached Data: none
// Reply: SERVER_TRUE if fonts have changed, SERVER_FALSE if not
needs_update=(code==SERVER_TRUE)?true:false;
}
#ifdef DEBUG_CLIENT_FONT_LIST
else
{
printf("ClientFontList::Update(): Couldn't find app_server port\n");
}
#endif
if(check_only)
{
delete serverlink;
release_sem(fontlock);
return needs_update;
}
// Don't update the list if nothing has changed
if(needs_update)
{
BFile file(SERVER_FONT_LIST,B_READ_ONLY);
BMessage fontmsg, familymsg;
if(file.InitCheck()==B_OK)
{
if(fontmsg.Unflatten(&file)==B_OK)
{
#ifdef DEBUG_CLIENT_FONT_LIST
printf("Font message contents:\n");
fontmsg.PrintToStream();
#endif
// Empty the font list
FontListFamily *flf=(FontListFamily*)familylist->RemoveItem(0L);
BString sty, extra;
int32 famindex, styindex;
bool tempbool;
while(flf)
{
#ifdef DEBUG_CLIENT_FONT_LIST
printf("Removing %s from list\n",flf->name.String());
#endif
delete flf;
flf=(FontListFamily*)familylist->RemoveItem(0L);
}
#ifdef DEBUG_CLIENT_FONT_LIST
printf("\n");
#endif
famindex=0;
// Repopulate with new listings
while(fontmsg.FindMessage("family",famindex,&familymsg)==B_OK)
{
famindex++;
flf=new FontListFamily();
familylist->AddItem(flf);
familymsg.FindString("name",&(flf->name));
#ifdef DEBUG_CLIENT_FONT_LIST
printf("Adding %s to list\n",flf->name.String());
#endif
styindex=0;
// populate family with styles
while(familymsg.FindString("styles",styindex,&sty)==B_OK)
{
#ifdef DEBUG_CLIENT_FONT_LIST
printf("\tAdding %s\n",sty.String());
#endif
styindex++;
flf->styles->AddItem(new BString(sty));
}
if(familymsg.FindBool("tuned",&tempbool)==B_OK)
{
#ifdef DEBUG_CLIENT_FONT_LIST
printf("Family %s has tuned fonts\n", flf->name.String());
#endif
flf->flags|=B_HAS_TUNED_FONT;
}
if(familymsg.FindBool("fixed",&tempbool)==B_OK)
{
#ifdef DEBUG_CLIENT_FONT_LIST
printf("Family %s is fixed-width\n", flf->name.String());
#endif
flf->flags|=B_IS_FIXED;
}
familymsg.MakeEmpty();
}
serverlink->SetOpCode(UPDATED_CLIENT_FONTLIST);
serverlink->Flush();
delete serverlink;
release_sem(fontlock);
return false;
} // end if Unflatten==B_OK
} // end if InitCheck==B_OK
} // end if needs_update
delete serverlink;
release_sem(fontlock);
return false;
}
int32 ClientFontList::CountFamilies(void)
{
#ifdef DEBUG_CLIENT_FONT_LIST
printf("ClientFontList::CountFamilies\n");
#endif
acquire_sem(fontlock);
int32 count=familylist->CountItems();
release_sem(fontlock);
return count;
}
status_t ClientFontList::GetFamily(int32 index, font_family *name, uint32 *flags=NULL)
{
#ifdef DEBUG_CLIENT_FONT_LIST
printf("ClientFontList::GetFamily(%ld)\n",index);
#endif
if(!name)
{
#ifdef DEBUG_CLIENT_FONT_LIST
printf("ClientFontList::GetFamily: NULL font_family parameter\n");
#endif
return B_ERROR;
}
acquire_sem(fontlock);
FontListFamily *flf=(FontListFamily*)familylist->ItemAt(index);
if(!flf)
{
#ifdef DEBUG_CLIENT_FONT_LIST
printf("ClientFontList::GetFamily: index not found\n");
#endif
return B_ERROR;
}
strcpy(*name,flf->name.String());
release_sem(fontlock);
return B_OK;
}
int32 ClientFontList::CountStyles(font_family f)
{
acquire_sem(fontlock);
FontListFamily *flf=NULL;
int32 i, count=familylist->CountItems();
bool found=false;
for(i=0; i<count;i++)
{
flf=(FontListFamily *)familylist->ItemAt(i);
if(!flf)
continue;
if(flf->name.ICompare(f)==0)
{
found=true;
break;
}
}
count=(found)?flf->styles->CountItems():0;
release_sem(fontlock);
return count;
}
status_t ClientFontList::GetStyle(font_family family, int32 index, font_style *name,uint32 *flags=NULL, uint16 *face=NULL)
{
if(!name || !(*name) || !family)
return B_ERROR;
acquire_sem(fontlock);
FontListFamily *flf=NULL;
BString *style;
int32 i, count=familylist->CountItems();
bool found=false;
for(i=0; i<count;i++)
{
flf=(FontListFamily *)familylist->ItemAt(i);
if(!flf)
continue;
if(flf->name.ICompare(family)==0)
{
found=true;
break;
}
}
if(!found)
{
release_sem(fontlock);
return B_ERROR;
}
style=(BString*)flf->styles->ItemAt(index);
if(!style)
{
release_sem(fontlock);
return B_ERROR;
}
strcpy(*name,style->String());
if(flags)
*flags=flf->flags;
if(face)
{
if(style->ICompare("Roman")==0 ||
style->ICompare("Regular")==0 ||
style->ICompare("Normal")==0 ||
style->ICompare("Light")==0 ||
style->ICompare("Medium")==0 ||
style->ICompare("Plain")==0)
{
*face|=B_REGULAR_FACE;
#ifdef DEBUG_FONTSERVER
printf("GetStyle: %s Roman face\n", style->String());
#endif
}
else
if(style->ICompare("Bold")==0)
{
*face|=B_BOLD_FACE;
#ifdef DEBUG_FONTSERVER
printf("GetStyle: %s Bold face\n");
#endif
}
else
if(style->ICompare("Italic")==0)
{
*face|=B_ITALIC_FACE;
#ifdef DEBUG_FONTSERVER
printf("GetStyle: %s Italic face\n");
#endif
}
else
if(style->ICompare("Bold Italic")==0)
{
*face|=B_ITALIC_FACE | B_BOLD_FACE;
#ifdef DEBUG_FONTSERVER
printf("GetStyle: %s Bold Italic face\n");
#endif
}
else
{
#ifdef DEBUG_FONTSERVER
printf("GetStyle: %s Unknown face %s\n", style->String());
#endif
}
}
release_sem(fontlock);
return B_OK;
}

View File

@ -0,0 +1,25 @@
#ifndef CLIENT_FONT_LIST_H
#define CLIENT_FONT_LIST_H
#include <Font.h> // for BFont-related definitions
#include <List.h>
#include <Message.h>
#include <OS.h>
class ClientFontList
{
public:
ClientFontList(void);
~ClientFontList(void);
bool Update(bool check_only);
int32 CountFamilies(void);
status_t GetFamily(int32 index, font_family *name, uint32 *flags=NULL);
int32 CountStyles(font_family f);
status_t GetStyle(font_family family, int32 index, font_style *name,uint32 *flags=NULL, uint16 *face=NULL);
private:
BList *familylist;
sem_id fontlock;
};
#endif

View File

@ -0,0 +1,219 @@
#include <iostream.h>
#include <stdio.h>
#include <String.h>
#include "DebugTools.h"
void PrintStatusToStream(status_t value)
{
// Function which simply translates a returned status code into a string
// and dumps it to stdout
BString outstr;
switch(value)
{
case B_OK:
outstr="B_OK ";
break;
case B_NAME_NOT_FOUND:
outstr="B_NAME_NOT_FOUND ";
break;
case B_BAD_VALUE:
outstr="B_BAD_VALUE ";
break;
case B_ERROR:
outstr="B_ERROR ";
break;
case B_TIMED_OUT:
outstr="B_TIMED_OUT ";
break;
case B_NO_MORE_PORTS:
outstr="B_NO_MORE_PORTS ";
break;
case B_WOULD_BLOCK:
outstr="B_WOULD_BLOCK ";
break;
case B_BAD_PORT_ID:
outstr="B_BAD_PORT_ID ";
break;
case B_BAD_TEAM_ID:
outstr="B_BAD_TEAM_ID ";
break;
default:
outstr="undefined status value in debugtools::PrintStatusToStream() ";
break;
}
cout << "Status: " << outstr.String() << endl << flush;
}
void PrintColorSpaceToStream(color_space value)
{
// Dump a color space to cout
BString outstr;
switch(value)
{
case B_RGB32:
outstr="B_RGB32 ";
break;
case B_RGBA32:
outstr="B_RGBA32 ";
break;
case B_RGB32_BIG:
outstr="B_RGB32_BIG ";
break;
case B_RGBA32_BIG:
outstr=" ";
break;
case B_UVL32:
outstr="B_UVL32 ";
break;
case B_UVLA32:
outstr="B_UVLA32 ";
break;
case B_LAB32:
outstr="B_LAB32 ";
break;
case B_LABA32:
outstr="B_LABA32 ";
break;
case B_HSI32:
outstr="B_HSI32 ";
break;
case B_HSIA32:
outstr="B_HSIA32 ";
break;
case B_HSV32:
outstr="B_HSV32 ";
break;
case B_HSVA32:
outstr="B_HSVA32 ";
break;
case B_HLS32:
outstr="B_HLS32 ";
break;
case B_HLSA32:
outstr="B_HLSA32 ";
break;
case B_CMY32:
outstr="B_CMY32";
break;
case B_CMYA32:
outstr="B_CMYA32 ";
break;
case B_CMYK32:
outstr="B_CMYK32 ";
break;
case B_RGB24_BIG:
outstr="B_RGB24_BIG ";
break;
case B_RGB24:
outstr="B_RGB24 ";
break;
case B_LAB24:
outstr="B_LAB24 ";
break;
case B_UVL24:
outstr="B_UVL24 ";
break;
case B_HSI24:
outstr="B_HSI24 ";
break;
case B_HSV24:
outstr="B_HSV24 ";
break;
case B_HLS24:
outstr="B_HLS24 ";
break;
case B_CMY24:
outstr="B_CMY24 ";
break;
case B_GRAY1:
outstr="B_GRAY1 ";
break;
case B_CMAP8:
outstr="B_CMAP8 ";
break;
case B_GRAY8:
outstr="B_GRAY8 ";
break;
case B_YUV411:
outstr="B_YUV411 ";
break;
case B_YUV420:
outstr="B_YUV420 ";
break;
case B_YCbCr422:
outstr="B_YCbCr422 ";
break;
case B_YCbCr411:
outstr="B_YCbCr411 ";
break;
case B_YCbCr420:
outstr="B_YCbCr420 ";
break;
case B_YUV422:
outstr="B_YUV422 ";
break;
case B_YUV9:
outstr="B_YUV9 ";
break;
case B_YUV12:
outstr="B_YUV12 ";
break;
case B_RGB15:
outstr="B_RGB15 ";
break;
case B_RGBA15:
outstr="B_RGBA15 ";
break;
case B_RGB16:
outstr="B_RGB16 ";
break;
case B_RGB16_BIG:
outstr="B_RGB16_BIG ";
break;
case B_RGB15_BIG:
outstr="B_RGB15_BIG ";
break;
case B_RGBA15_BIG:
outstr="B_RGBA15_BIG ";
break;
case B_YCbCr444:
outstr="B_YCbCr444 ";
break;
case B_YUV444:
outstr="B_YUV444 ";
break;
case B_NO_COLOR_SPACE:
outstr="B_NO_COLOR_SPACE ";
break;
default:
outstr="Undefined color space ";
break;
}
cout << "Color Space: " << outstr.String() << flush;
}
void TranslateMessageCodeToStream(int32 code)
{
// Used to translate BMessage message codes back to a character
// format
cout << "'"
<< (char)((code & 0xFF000000) >> 24)
<< (char)((code & 0x00FF0000) >> 16)
<< (char)((code & 0x0000FF00) >> 8)
<< (char)((code & 0x000000FF)) << "' ";
}
void PrintMessageCode(int32 code)
{
// Used to translate BMessage message codes back to a character
// format
printf("Message code %c%c%c%c\n",
(char)((code & 0xFF000000) >> 24),
(char)((code & 0x00FF0000) >> 16),
(char)((code & 0x0000FF00) >> 8),
(char)((code & 0x000000FF)) );
}

View File

@ -0,0 +1,12 @@
#ifndef _DEBUGTOOLS_H_
#define _DEBUGTOOLS_H_
#include <SupportDefs.h>
#include <GraphicsDefs.h>
void PrintStatusToStream(status_t value);
void PrintColorSpaceToStream(color_space value);
void TranslateMessageCodeToStream(int32 code);
void PrintMessageCode(int32 code);
#endif

View File

@ -0,0 +1,13 @@
SubDir OBOS_TOP src servers app proto7 testobapp ;
App proto7_test_app :
<$(SOURCE_GRIST)>ClientFontList.cpp
<$(SOURCE_GRIST)>DebugTools.cpp
<$(SOURCE_GRIST)>OBApplication.cpp
<$(SOURCE_GRIST)>OBFont.cpp
<$(SOURCE_GRIST)>OBTestApp.cpp
<$(SOURCE_GRIST)>OBView.cpp
<$(SOURCE_GRIST)>OBWindow.cpp
<$(SOURCE_GRIST)>PortLink.cpp
;
LinkSharedOSLibs OBApplication : be stdc++.r4 ;

View File

@ -0,0 +1,390 @@
/*
OBApplication.cpp:
Beginning framework for a *real* BApplication replacement for the prototypes
*/
#include <OS.h>
#include <GraphicsDefs.h> // for the pattern struct and screen mode defs
#include <Rect.h>
#include <Region.h>
#include <Cursor.h>
#include <Font.h>
#include <Application.h>
#include <Handler.h>
#include <Message.h>
#include <stdio.h>
#include <String.h>
#include <List.h>
#include "ServerProtocol.h"
#include "PortLink.h"
#include "OBApplication.h"
#include "OBWindow.h"
#include "DebugTools.h"
#include "OBFont.h"
class OBFont;
OBApplication *obe_app;
OBFont *obe_plain_font=NULL;
OBFont *obe_bold_font=NULL;
OBFont *obe_fixed_font=NULL;
#define DEBUG_OBAPP
OBApplication::OBApplication(const char *sig) : BApplication(sig)
{
if(sig)
signature=new BString(sig);
else
signature=new BString("application/x-vnd.obos-OBApplication");
#ifdef DEBUG_OBAPP
printf("OBApplication(%s)\n",signature->String());
#endif
// A BApplication is locked on start, but because this is not a "real"
// one, we do not actually lock it.
initcheckval=B_OK;
// Receives messages from server and others
messageport=create_port(50,"msgport");
if(messageport==B_BAD_VALUE || messageport==B_NO_MORE_PORTS)
{
printf("OBApplication: Couldn't create message port\n");
initcheckval=B_ERROR;
}
// Find the port for the app_server
serverport=find_port("OBappserver");
if(serverport==B_NAME_NOT_FOUND)
{
printf("OBApplication: Couldn't find server port\n");
serverlink=NULL;
write_port(messageport,B_QUIT_REQUESTED,NULL,0);
initcheckval=B_ERROR;
}
else
{
serverlink=new PortLink(serverport);
#ifdef DEBUG_OBAPP
printf("OBApplication(%s): App Server Port %ld\n",signature->String(),serverport);
#endif
// Notify server of app's existence
int32 replycode;
status_t replystat;
ssize_t replysize;
int8 *replybuffer;
serverlink->SetOpCode(CREATE_APP);
serverlink->Attach(&messageport,sizeof(port_id));
// serverlink.Attach(PID);
serverlink->Attach((char*)signature->String(),strlen(signature->String()));
// Send and wait for ServerApp port. Necessary here (as opposed to start
// of message loop) in case any windows are created in application constructor
replybuffer=serverlink->FlushWithReply(&replycode,&replystat,&replysize);
serverport=*((port_id*)replybuffer);
serverlink->SetPort(serverport);
delete replybuffer;
#ifdef DEBUG_OBAPP
printf("OBApplication(%s): ServerApp Port %ld\n",signature->String(),serverport);
#endif
ReadyToRun();
}
obe_app=this;
windowlist=new BList(0);
}
OBApplication::~OBApplication(void)
{
#ifdef DEBUG_OBAPP
printf("%s::~OBApplication()\n",signature->String());
#endif
delete signature;
if(serverlink)
delete serverlink;
// OBWindow *win;
// for(int32 i=0; i<windowlist->CountItems(); i++)
// {
// win=(OBWindow*)windowlist->RemoveItem(i);
// if(win)
// win->Quit();
// }
delete windowlist;
}
status_t OBApplication::InitCheck(void) const
{
// Called to make sure everything in the constructor turned out ok. If it didn't,
// the application falls through and the process ends.
return initcheckval;
}
void OBApplication::MainLoop(void)
{
#ifdef DEBUG_OBAPP
printf("%s::MainLoop()\n",signature->String());
#endif
int32 msgcode;
uint8 *msgbuffer=NULL;
ssize_t buffersize,bytesread;
for(;;)
{
// Modified this slightly so that OBApplications will eventually time out
// if the server crashes. Saves on a lot of Ctrl-Alt-Del's. :) CPU time is
// saved by setting the timeout to 3 seconds - more than enough time.
if(find_thread("OBAppServer")==B_NAME_NOT_FOUND)
{
printf("%s lost connection with server. Quitting.\n",signature->String());
break;
}
buffersize=port_buffer_size_etc(messageport,B_TIMEOUT,300000);
if(buffersize==B_TIMED_OUT)
continue;
if(buffersize>0)
{
// buffers are flattened messages. Allocate necessary buffer and
// we'll cast it as a BMessage.
msgbuffer=new uint8[buffersize];
bytesread=read_port(messageport,&msgcode,msgbuffer,buffersize);
}
else
bytesread=read_port(messageport,&msgcode,NULL,0);
if (bytesread != B_BAD_PORT_ID && bytesread != B_TIMED_OUT && bytesread != B_WOULD_BLOCK)
{
switch(msgcode)
{
case B_QUIT_REQUESTED:
{
// Attached data:
// None
// printf("%s: Quit requested\n",signature);
serverlink->SetOpCode(msgcode);
serverlink->Flush();
break;
}
case ADDWINDOW:
{
// This message is received by a window's constructor so that it
// can be added to the window list
// Attached Data:
// 1) OBWindow *window
// I hope this is the right syntax...
windowlist->AddItem(msgbuffer);
#ifdef DEBUG_OBAPP
printf("%s: Add Window @ %p\n",signature->String(),msgbuffer);
#endif
break;
}
case REMOVEWINDOW:
{
// This message is received by a window's constructor so that it
// can be added to the window list
// Attached Data:
// 1) OBWindow *window
// I hope this is the right syntax...
windowlist->RemoveItem(msgbuffer);
#ifdef DEBUG_OBAPP
printf("%s: Remove Window @ %p\n",signature->String(),msgbuffer);
#endif
break;
}
case B_MOUSE_MOVED:
case B_MOUSE_DOWN:
case B_MOUSE_UP:
DispatchMessage(msgcode, (int8*)msgbuffer);
break;
// Later on, this will default to passing the message to
// DispatchMessage(BMessage*, BHandler*)
default:
printf("OBApplication received unexpected code %ld - ",msgcode);
PrintMessageCode(msgcode);
break;
}
if(msgcode==B_QUIT_REQUESTED)
{
printf("Quitting %s\n",signature->String());
break;
}
}
if(buffersize>0)
delete msgbuffer;
}
}
void OBApplication::DispatchMessage(BMessage *msg, BHandler *handler)
{
#ifdef DEBUG_OBAPP
printf("%s::DispatchMessage(BMessage*,BHandler*)\n",signature->String());
#endif
BApplication::DispatchMessage(msg,handler);
}
void OBApplication::DispatchMessage(int32 code, int8 *buffer)
{
// This function will be necessary to handle server messages.
switch(code)
{
case B_MOUSE_DOWN:
case B_MOUSE_UP:
case B_MOUSE_MOVED:
break;
default:
printf("OBApplication %s received unknown code %ld\n",signature->String(),code);
break;
}
}
void OBApplication::MessageReceived(BMessage *msg)
{
#ifdef DEBUG_OBAPP
printf("%s::MessageReceived()\n",signature->String());
#endif
}
void OBApplication::ShowCursor(void)
{
#ifdef DEBUG_OBAPP
printf("%s::ShowCursor()\n",signature->String());
#endif
serverlink->SetOpCode(SHOW_CURSOR);
serverlink->Flush();
}
void OBApplication::HideCursor(void)
{
#ifdef DEBUG_OBAPP
printf("%s::HideCursor()\n",signature->String());
#endif
serverlink->SetOpCode(HIDE_CURSOR);
serverlink->Flush();
}
void OBApplication::ObscureCursor(void)
{
#ifdef DEBUG_OBAPP
printf("%s::ObscureCursor()\n",signature->String());
#endif
serverlink->SetOpCode(OBSCURE_CURSOR);
serverlink->Flush();
}
bool OBApplication::IsCursorHidden(void) const
{
return false;
}
void OBApplication::SetCursor(const void *cursor)
{
#ifdef DEBUG_OBAPP
printf("%s::SetCursor()\n",signature->String());
#endif
// attach & send the 68-byte chunk
serverlink->SetOpCode(SET_CURSOR_DATA);
serverlink->Attach((void*)cursor, 68);
serverlink->Flush();
}
thread_id OBApplication::Run(void)
{
#ifdef DEBUG_OBAPP
printf("%s::Run()\n",signature->String());
#endif
if(initcheckval==B_OK)
MainLoop();
return 0;
}
status_t OBApplication::Archive(BMessage *data, bool deep = true) const
{
return B_ERROR;
}
void OBApplication::Quit(void)
{
#ifdef DEBUG_OBAPP
printf("%s::Quit()\n",signature->String());
#endif
OBWindow *win;
while(windowlist->CountItems()>0)
{
win=(OBWindow*)windowlist->RemoveItem(0L);
if(win)
win->Quit();
}
BApplication::Quit();
}
bool OBApplication::QuitRequested(void)
{
#ifdef DEBUG_OBAPP
printf("%s::QuitRequested()\n",signature->String());
#endif
return true;
}
void OBApplication::Pulse(void)
{
}
void OBApplication::ArgvReceived(int32 argc, char **argv)
{
}
void OBApplication::AppActivated(bool active)
{
}
void OBApplication::RefsReceived(BMessage *a_message)
{
}
void OBApplication::AboutRequested(void)
{
}
BHandler *OBApplication::ResolveSpecifier(BMessage *msg,int32 index,BMessage *specifier,
int32 form,const char *property)
{
return NULL;
}
status_t OBApplication::GetSupportedSuites(BMessage *data)
{
return B_ERROR;
}
status_t OBApplication::Perform(perform_code d, void *arg)
{
return B_ERROR;
}
void OBApplication::ReadyToRun(void)
{
#ifdef DEBUG_OBAPP
printf("%s::ReadyToRun()\n",signature->String());
#endif
}

View File

@ -0,0 +1,71 @@
#ifndef _OBOS_APPLICATION_H_
#define _OBOS_APPLICATION_H_
#include <SupportDefs.h>
#include <Application.h>
class PortLink;
class BList;
class OBWindow;
class OBApplication : private BApplication
{
public:
OBApplication(const char *signature);
OBApplication(const char *signature, status_t *error);
virtual ~OBApplication(void);
OBApplication(BMessage *data);
static BArchivable *Instantiate(BMessage *data);
virtual status_t Archive(BMessage *data, bool deep = true) const;
status_t InitCheck() const;
virtual thread_id Run(void);
virtual void Quit(void);
virtual bool QuitRequested(void);
virtual void Pulse(void);
virtual void ReadyToRun(void);
virtual void MessageReceived(BMessage *msg);
virtual void ArgvReceived(int32 argc, char **argv);
virtual void AppActivated(bool active);
virtual void RefsReceived(BMessage *a_message);
virtual void AboutRequested(void);
virtual BHandler *ResolveSpecifier(BMessage *msg,int32 index,
BMessage *specifier,int32 form,const char *property);
void ShowCursor(void);
void HideCursor(void);
void ObscureCursor(void);
bool IsCursorHidden(void) const;
void SetCursor(const void *cursor);
void SetCursor(const BCursor *cursor, bool sync=true);
int32 CountWindows(void) const;
BWindow *WindowAt(int32 index) const;
int32 CountLoopers(void) const;
BLooper *LooperAt(int32 index) const;
bool IsLaunching(void) const;
status_t GetAppInfo(app_info *info) const;
static BResources *AppResources(void);
virtual void DispatchMessage(BMessage *an_event,BHandler *handler);
void SetPulseRate(bigtime_t rate);
virtual status_t GetSupportedSuites(BMessage *data);
virtual status_t Perform(perform_code d, void *arg);
protected:
friend OBWindow;
void MainLoop(void);
void DispatchMessage(int32 code, int8 *buffer);
port_id messageport, serverport;
BString *signature;
PortLink *serverlink;
BList *windowlist;
status_t initcheckval;
};
extern OBApplication *obe_app;
#endif

View File

@ -0,0 +1,516 @@
#include <Rect.h>
#include <stdio.h>
#include <string.h>
#include "ClientFontList.h"
#include "OBFont.h"
class OBFont;
extern ClientFontList *client_font_list;
class OBFontPrivate
{
public:
OBFontPrivate(void);
OBFontPrivate &operator=(const OBFontPrivate &fontdata);
BRect fBox;
font_family fFamily;
font_style fStyle;
bool fFixed;
font_file_format fFormat;
font_direction fDirection;
int32 fPrivateFlags;
};
OBFontPrivate::OBFontPrivate(void)
{
fBox=BRect(0,0,0,0);
strcpy(fFamily,"\0");
strcpy(fStyle,"\0");
fFixed=false;
fFormat=B_TRUETYPE_WINDOWS;
fDirection=B_FONT_LEFT_TO_RIGHT;
fPrivateFlags=0;
}
OBFontPrivate & OBFontPrivate::operator=(const OBFontPrivate &fontdata)
{
fBox=fontdata.fBox;
*fFamily=*(fontdata.fFamily);
*fStyle=*(fontdata.fStyle);
fFixed=fontdata.fFixed;
fFormat=fontdata.fFormat;
fDirection=fontdata.fDirection;
fPrivateFlags=fontdata.fPrivateFlags;
return *this;
}
OBFont::OBFont(void)
{
private_data=new OBFontPrivate();
if(be_plain_font)
{
fFamilyID=obe_plain_font->fFamilyID;
fStyleID=obe_plain_font->fStyleID;
fSize=obe_plain_font->fSize;
fShear=obe_plain_font->fShear;
fRotation=obe_plain_font->fRotation;
fSpacing=obe_plain_font->fSpacing;
fEncoding=obe_plain_font->fEncoding;
fFace=obe_plain_font->fFace;
fHeight=obe_plain_font->fHeight;
private_data=obe_plain_font->private_data;
}
else
{
fFamilyID=0;
fStyleID=0;
fSize=0.0;
fShear=90.0;
fRotation=0.0;
fSpacing=B_CHAR_SPACING;
fEncoding=B_UNICODE_UTF8;
fFace=B_REGULAR_FACE;
fHeight.ascent=0.0;
fHeight.descent=0.0;
fHeight.leading=0.0;
private_data->fPrivateFlags=0;
}
}
OBFont::OBFont(const OBFont &font)
{
private_data=new OBFontPrivate();
fFamilyID=font.fFamilyID;
fStyleID=font.fStyleID;
fSize=font.fSize;
fShear=font.fShear;
fRotation=font.fRotation;
fSpacing=font.fSpacing;
fEncoding=font.fEncoding;
fFace=font.fFace;
fHeight=font.fHeight;
private_data=font.private_data;
}
OBFont::OBFont(const OBFont *font)
{
private_data=new OBFontPrivate();
if(font)
{
fFamilyID=font->fFamilyID;
fStyleID=font->fStyleID;
fSize=font->fSize;
fShear=font->fShear;
fRotation=font->fRotation;
fSpacing=font->fSpacing;
fEncoding=font->fEncoding;
fFace=font->fFace;
fHeight=font->fHeight;
private_data=font->private_data;
}
else
{
if(obe_plain_font)
{
fFamilyID=obe_plain_font->fFamilyID;
fStyleID=obe_plain_font->fStyleID;
fSize=obe_plain_font->fSize;
fShear=obe_plain_font->fShear;
fRotation=obe_plain_font->fRotation;
fSpacing=obe_plain_font->fSpacing;
fEncoding=obe_plain_font->fEncoding;
fFace=obe_plain_font->fFace;
fHeight=obe_plain_font->fHeight;
private_data=obe_plain_font->private_data;
}
else
{
fFamilyID=0;
fStyleID=0;
fSize=0.0;
fShear=90.0;
fRotation=0.0;
fSpacing=B_CHAR_SPACING;
fEncoding=B_UNICODE_UTF8;
fFace=B_REGULAR_FACE;
fHeight.ascent=0.0;
fHeight.descent=0.0;
fHeight.leading=0.0;
private_data->fPrivateFlags=0;
}
}
}
OBFont::~OBFont(void)
{
delete private_data;
}
status_t OBFont::SetFamilyAndStyle(const font_family family, const font_style style)
{
// TODO: implement
// TODO: find out what codes are returned by this function. Be Book says this returns nothing
// Query server for the appropriate family and style IDs and then return the
// appropriate value
return B_ERROR;
}
void OBFont::SetFamilyAndStyle(uint32 code)
{
fStyleID=code & 0xFFFF;
fFamilyID=(code & 0xFFFF0000) >> 16;
}
status_t OBFont::SetFamilyAndFace(const font_family family, uint16 face)
{
// TODO: find out what codes are returned by this function. Be Book says this returns nothing
fFace=face;
// TODO: finish this function by adding the app_server Family query protocol code
if(family)
{
// Query server for family id for the specified family
}
return B_OK;
}
void OBFont::SetSize(float size)
{
fSize=size;
}
void OBFont::SetShear(float shear)
{
fShear=shear;
}
void OBFont::SetRotation(float rotation)
{
fRotation=rotation;
}
void OBFont::SetSpacing(uint8 spacing)
{
fSpacing=spacing;
}
void OBFont::SetEncoding(uint8 encoding)
{
fEncoding=encoding;
}
void OBFont::SetFace(uint16 face)
{
fFace=face;
}
void OBFont::SetFlags(uint32 flags)
{
fFlags=flags;
}
void OBFont::GetFamilyAndStyle(font_family *family, font_style *style) const
{
if(!family | !style)
return;
// TODO: implement
// Query server for the names of this stuff given the family and style IDs kept internally
strcpy((char *)family,private_data->fFamily);
strcpy((char *)style,private_data->fStyle);
}
uint32 OBFont::FamilyAndStyle(void) const
{
uint32 token;
token=(fFamilyID << 16) | fStyleID;
return 0L;
}
float OBFont::Size(void) const
{
return fSize;
}
float OBFont::Shear(void) const
{
return fShear;
}
float OBFont::Rotation(void) const
{
return fRotation;
}
uint8 OBFont::Spacing(void) const
{
return fSpacing;
}
uint8 OBFont::Encoding(void) const
{
return fEncoding;
}
uint16 OBFont::Face(void) const
{
return fFace;
}
uint32 OBFont::Flags(void) const
{
return fFlags;
}
font_direction OBFont::Direction(void) const
{
return B_FONT_LEFT_TO_RIGHT;
}
bool OBFont::IsFixed(void) const
{
// TODO: query server for whether this bad boy is fixed-width
return false;
}
bool OBFont::IsFullAndHalfFixed(void) const
{
return false;
}
BRect OBFont::BoundingBox(void) const
{
// TODO: query server for bounding box
return BRect(0,0,0,0);
}
unicode_block OBFont::Blocks(void) const
{
// TODO: Add Block support
return unicode_block();
}
font_file_format OBFont::FileFormat(void) const
{
// TODO: this will not work until I extend FreeType to handle this kind of call
return B_TRUETYPE_WINDOWS;
}
int32 OBFont::CountTuned(void) const
{
// TODO: query server for appropriate data
return 0;
}
void OBFont::GetTunedInfo(int32 index, tuned_font_info *info) const
{
// TODO: implement
}
void OBFont::TruncateString(BString *in_out,uint32 mode,float width) const
{
// TODO: implement
}
void OBFont::GetTruncatedStrings(const char *stringArray[], int32 numStrings,
uint32 mode, float width, BString resultArray[]) const
{
// TODO: implement
}
void OBFont::GetTruncatedStrings(const char *stringArray[], int32 numStrings,
uint32 mode, float width, char *resultArray[]) const
{
// TODO: implement
}
float OBFont::StringWidth(const char *string) const
{
// TODO: implement
return 0.0;
}
float OBFont::StringWidth(const char *string, int32 length) const
{
// TODO: implement
return 0.0;
}
void OBFont::GetStringWidths(const char *stringArray[], const int32 lengthArray[],
int32 numStrings, float widthArray[]) const
{
// TODO: implement
}
void OBFont::GetEscapements(const char charArray[], int32 numChars, float escapementArray[]) const
{
// TODO: implement
}
void OBFont::GetEscapements(const char charArray[], int32 numChars, escapement_delta *delta,
float escapementArray[]) const
{
// TODO: implement
}
void OBFont::GetEscapements(const char charArray[], int32 numChars, escapement_delta *delta,
BPoint escapementArray[]) const
{
// TODO: implement
}
void OBFont::GetEscapements(const char charArray[], int32 numChars, escapement_delta *delta,
BPoint escapementArray[], BPoint offsetArray[]) const
{
// TODO: implement
}
void OBFont::GetEdges(const char charArray[], int32 numBytes, edge_info edgeArray[]) const
{
// TODO: implement
}
void OBFont::GetHeight(font_height *height) const
{
if(height)
{
*height=fHeight;
}
}
void OBFont::GetBoundingBoxesAsGlyphs(const char charArray[], int32 numChars, font_metric_mode mode,
BRect boundingBoxArray[]) const
{
// TODO: implement
}
void OBFont::GetBoundingBoxesAsString(const char charArray[], int32 numChars, font_metric_mode mode,
escapement_delta *delta, BRect boundingBoxArray[]) const
{
// TODO: implement
}
void OBFont::GetBoundingBoxesForStrings(const char *stringArray[], int32 numStrings,
font_metric_mode mode, escapement_delta deltas[], BRect boundingBoxArray[]) const
{
// TODO: implement
}
void OBFont::GetGlyphShapes(const char charArray[], int32 numChars, BShape *glyphShapeArray[]) const
{
// TODO: implement
}
void OBFont::GetHasGlyphs(const char charArray[], int32 numChars, bool hasArray[]) const
{
// TODO: implement
}
OBFont &OBFont::operator=(const OBFont &font)
{
fFamilyID=font.fFamilyID;
fStyleID=font.fStyleID;
fSize=font.fSize;
fShear=font.fShear;
fRotation=font.fRotation;
fSpacing=font.fSpacing;
fEncoding=font.fEncoding;
fFace=font.fFace;
fHeight=font.fHeight;
private_data->fPrivateFlags=font.private_data->fPrivateFlags;
return *this;
}
bool OBFont::operator==(const OBFont &font) const
{
if( fFamilyID!=font.fFamilyID ||
fStyleID!=font.fStyleID ||
fSize!=font.fSize ||
fShear!=font.fShear ||
fRotation!=font.fRotation ||
fSpacing!=font.fSpacing ||
fEncoding!=font.fEncoding ||
fFace!=font.fFace ||
fHeight.ascent!=font.fHeight.ascent ||
fHeight.descent!=font.fHeight.descent ||
fHeight.leading!=font.fHeight.leading ||
private_data->fPrivateFlags!=font.private_data->fPrivateFlags )
return false;
return true;
}
bool OBFont::operator!=(const OBFont &font) const
{
if( fFamilyID!=font.fFamilyID ||
fStyleID!=font.fStyleID ||
fSize!=font.fSize ||
fShear!=font.fShear ||
fRotation!=font.fRotation ||
fSpacing!=font.fSpacing ||
fEncoding!=font.fEncoding ||
fFace!=font.fFace ||
fHeight.ascent!=font.fHeight.ascent ||
fHeight.descent!=font.fHeight.descent ||
fHeight.leading!=font.fHeight.leading ||
private_data->fPrivateFlags!=font.private_data->fPrivateFlags )
return true;
return false;
}
void OBFont::PrintToStream(void) const
{
printf("FAMILY STYLE %f %f %f %f %f %f\n", fSize, fShear, fRotation, fHeight.ascent,
fHeight.descent, fHeight.leading);
}
int32 ob_count_font_families(void)
{
return client_font_list->CountFamilies();
}
status_t ob_get_font_family(int32 index, font_family *name, uint32 *flags=NULL)
{
return client_font_list->GetFamily(index,name,flags);
}
int32 ob_count_font_styles(font_family name)
{
return client_font_list->CountStyles(name);
}
status_t ob_get_font_style(font_family family, int32 index, font_style *name, uint32 *flags=NULL)
{
return client_font_list->GetStyle(family,index,name,flags);
}
status_t ob_get_font_style(font_family family, int32 index, font_style *name,
uint16 *face, uint32 *flags=NULL)
{
return client_font_list->GetStyle(family,index,name,flags,face);
}
bool ob_update_font_families(bool check_only)
{
return client_font_list->Update(check_only);
}
status_t ob_get_font_cache_info(uint32 id, void *set)
{
// lame duck undocumented function
return B_OK;
}
status_t ob_set_font_cache_info(uint32 id, void *set)
{
// lame duck undocumented function
return B_OK;
}

View File

@ -0,0 +1,189 @@
#ifndef OBFONT_H_
#define OBFONT_H_
#include <BeBuild.h>
#include <SupportDefs.h>
#include <InterfaceDefs.h>
#include <Font.h> // for various font structure definitions
class BShape;
class BString;
class OBFontPrivate;
class OBFont {
public:
OBFont(void);
OBFont(const OBFont &font);
OBFont(const OBFont *font);
~OBFont(void);
status_t SetFamilyAndStyle(const font_family family,
const font_style style);
void SetFamilyAndStyle(uint32 code);
status_t SetFamilyAndFace(const font_family family, uint16 face);
void SetSize(float size);
void SetShear(float shear);
void SetRotation(float rotation);
void SetSpacing(uint8 spacing);
void SetEncoding(uint8 encoding);
void SetFace(uint16 face);
void SetFlags(uint32 flags);
void GetFamilyAndStyle(font_family *family,
font_style *style) const;
uint32 FamilyAndStyle(void) const;
float Size(void) const;
float Shear(void) const;
float Rotation(void) const;
uint8 Spacing(void) const;
uint8 Encoding(void) const;
uint16 Face(void) const;
uint32 Flags(void) const;
font_direction Direction(void) const;
bool IsFixed(void) const;
bool IsFullAndHalfFixed(void) const;
BRect BoundingBox(void) const;
unicode_block Blocks(void) const;
font_file_format FileFormat(void) const;
int32 CountTuned(void) const;
void GetTunedInfo(int32 index, tuned_font_info *info) const;
void TruncateString(BString* in_out,
uint32 mode,
float width) const;
void GetTruncatedStrings(const char *stringArray[],
int32 numStrings,
uint32 mode,
float width,
BString resultArray[]) const;
void GetTruncatedStrings(const char *stringArray[],
int32 numStrings,
uint32 mode,
float width,
char *resultArray[]) const;
float StringWidth(const char *string) const;
float StringWidth(const char *string, int32 length) const;
void GetStringWidths(const char *stringArray[],
const int32 lengthArray[],
int32 numStrings,
float widthArray[]) const;
void GetEscapements(const char charArray[],
int32 numChars,
float escapementArray[]) const;
void GetEscapements(const char charArray[],
int32 numChars,
escapement_delta *delta,
float escapementArray[]) const;
void GetEscapements(const char charArray[],
int32 numChars,
escapement_delta *delta,
BPoint escapementArray[]) const;
void GetEscapements(const char charArray[],
int32 numChars,
escapement_delta *delta,
BPoint escapementArray[],
BPoint offsetArray[]) const;
void GetEdges(const char charArray[],
int32 numBytes,
edge_info edgeArray[]) const;
void GetHeight(font_height *height) const;
void GetBoundingBoxesAsGlyphs(const char charArray[],
int32 numChars,
font_metric_mode mode,
BRect boundingBoxArray[]) const;
void GetBoundingBoxesAsString(const char charArray[],
int32 numChars,
font_metric_mode mode,
escapement_delta *delta,
BRect boundingBoxArray[]) const;
void GetBoundingBoxesForStrings(const char *stringArray[],
int32 numStrings,
font_metric_mode mode,
escapement_delta deltas[],
BRect boundingBoxArray[]) const;
void GetGlyphShapes(const char charArray[],
int32 numChars,
BShape *glyphShapeArray[]) const;
void GetHasGlyphs(const char charArray[],
int32 numChars,
bool hasArray[]) const;
OBFont& operator=(const OBFont &font);
bool operator==(const OBFont &font) const;
bool operator!=(const OBFont &font) const;
void PrintToStream(void) const;
private:
uint16 fFamilyID;
uint16 fStyleID;
float fSize;
float fShear;
float fRotation;
uint8 fSpacing;
uint8 fEncoding;
uint16 fFace;
uint32 fFlags;
font_height fHeight;
OBFontPrivate *private_data;
uint32 _reserved[2];
void SetPacket(void *packet) const;
void GetTruncatedStrings64(const char *stringArray[],
int32 numStrings,
uint32 mode,
float width,
char *resultArray[]) const;
void GetTruncatedStrings64(const char *stringArray[],
int32 numStrings,
uint32 mode,
float width,
BString resultArray[]) const;
void _GetEscapements_(const char charArray[],
int32 numChars,
escapement_delta *delta,
uint8 mode,
float *escapements,
float *offsets = NULL) const;
void _GetBoundingBoxes_(const char charArray[],
int32 numChars,
font_metric_mode mode,
bool string_escapement,
escapement_delta *delta,
BRect boundingBoxArray[]) const;
};
/*----------------------------------------------------------------*/
/*----- OBFont related declarations -------------------------------*/
//extern const OBFont *obe_plain_font;
//extern const OBFont *obe_bold_font;
//extern const OBFont *obe_fixed_font;
extern OBFont *obe_plain_font;
extern OBFont *obe_bold_font;
extern OBFont *obe_fixed_font;
int32 ob_count_font_families(void);
status_t ob_get_font_family(int32 index, font_family *name, uint32 *flags=NULL);
int32 ob_count_font_styles(font_family name);
status_t ob_get_font_style(font_family family, int32 index, font_style *name,
uint32 *flags=NULL);
status_t ob_get_font_style(font_family family, int32 index, font_style *name,
uint16 *face, uint32 *flags=NULL);
bool ob_update_font_families(bool check_only);
status_t ob_get_font_cache_info(uint32 id, void *set);
status_t ob_set_font_cache_info(uint32 id, void *set);
#endif

View File

@ -0,0 +1,39 @@
#include "OBApplication.h"
#include "OBWindow.h"
#include "OBView.h"
#include "ClientFontList.h"
ClientFontList *client_font_list;
class OBTestApp : public OBApplication
{
public:
OBTestApp(void);
~OBTestApp(void);
};
OBWindow *win;
OBTestApp::OBTestApp(void) : OBApplication("application/OBTestApp")
{
win=new OBWindow(BRect(100,100,200,200), "OBWindow1",B_FLOATING_WINDOW_LOOK,
B_NORMAL_WINDOW_FEEL,0);
win->Show();
}
OBTestApp::~OBTestApp(void)
{
}
int main(void)
{
client_font_list=new ClientFontList();
client_font_list->Update(false);
OBTestApp *app=new OBTestApp();
app->Run();
delete app;
delete client_font_list;
}

View File

@ -0,0 +1,880 @@
#include <stdio.h>
#include <Region.h>
#include "PortLink.h"
#include "ServerProtocol.h"
#include "OBView.h"
#include "OBWindow.h"
//#define DEBUG_VIEW
#ifndef SET_RGB_COLOR
#define SET_RGB_COLOR(a,b,c,d,e) a.red=b; a.green=c; a.blue=d; a.alpha=e;
#endif
OBView::OBView(BRect frame,const char *name,uint32 resizeMask,uint32 flags)
: BHandler(name)
{
viewflags=flags;
resizeflags=resizeMask;
origin_h=0.0;
origin_v=0.0;
owner=NULL;
parent=NULL;
uppersibling=NULL;
lowersibling=NULL;
topchild=NULL;
bottomchild=NULL;
hidelevel=0;
// This will be changed when added to a BWindow as the top view
topview=false;
SET_RGB_COLOR(highcol,0,0,0,255);
SET_RGB_COLOR(lowcol,255,255,255,255);
SET_RGB_COLOR(viewcol,255,255,255,255);
// We need to align to the nearest pixel, rounded down
// There's probably a better way to do this, but it'll work for now...
vframe.left=(int32)frame.left;
vframe.top=(int32)frame.top;
vframe.right=(int32)frame.right;
vframe.bottom=(int32)frame.bottom;
}
OBView::~OBView()
{
// Be Book says it's an error to delete while attached to a window.
// We'll just prevent that problem...
if(owner)
{
// No, this isn't an error to utilize parent and not owner. We
// aren't actually attached to the window class itself. We're
// attached to a view which is a member of the window.
parent->RemoveChild(this);
}
OBView *v;
for(v=topchild; v!=NULL; v=v->lowersibling)
delete v;
}
void OBView::AttachedToWindow()
{
// Hook function
}
void OBView::AllAttached()
{
// Hook function
}
void OBView::DetachedFromWindow()
{
// Hook function
}
void OBView::AllDetached()
{
// Hook function
}
void OBView::MessageReceived(BMessage *msg)
{
// Adds scripting support to the BHandler version. This is
// only a skeleton implementation, so it has been skipped
BHandler::MessageReceived(msg);
}
void OBView::AddChild(OBView *child, OBView *before = NULL)
{
if(!child)
return;
if(child->parent || child->owner)
{
printf("%s::AddChild(): child already has a parent\n",Name());
return;
}
if(child->parent==this)
{
printf("%s::AddChild(): child already belongs to view\n",Name());
return;
}
// Adds a layer to the top of the layer's children
#ifdef DEBUG_VIEW
printf("%s::AddChild(%s)\n", Name(), child->Name());
#endif
child->parent=this;
child->owner=owner;
// View specified. Add new child above the specified view
if(before)
{
if(before->parent==this)
{
child->lowersibling=before;
child->uppersibling=before->uppersibling;
before->uppersibling->lowersibling=child;
before->uppersibling=child;
// If we're attached to a window, notify all child views of
// their attachment
if(owner)
{
CallAttached(child);
child->AllAttached();
}
}
else
{
printf("%s::AddChild(): Can't add %s before %s - different parents\n",
Name(), child->Name(), before->Name());
}
return;
}
// If we haven't specified, child is added to bottom of list
if(bottomchild!=NULL)
{
child->uppersibling=bottomchild;
bottomchild->lowersibling=child;
}
bottomchild=child;
}
bool OBView::RemoveChild(OBView *child)
{
if(!child)
return false;
if(child->parent!=this)
{
printf("%s::RemoveChild(): %s not child of this view\n",Name(),child->Name());
return false;
}
// Adds a layer to the top of the layer's children
#ifdef DEBUG_VIEW
printf("%s::RemoveChild(%s)\n", Name(), child->Name());
#endif
if(owner)
{
CallDetached(child);
// We only need to tell the server to prune the layer tree
// at the child's level
PortLink *link=new PortLink(owner->outport);
link->SetOpCode(LAYER_DELETE);
link->Attach(child->id);
link->Flush();
delete link;
}
// Note that we do the pointer reassignments last because the other
// function calls made in RemoveChild() depend on these pointers
if(topchild==child)
topchild=child->lowersibling;
if(bottomchild==child)
bottomchild=child->lowersibling;
if(child->uppersibling!=NULL)
child->uppersibling->lowersibling=child->lowersibling;
if(child->lowersibling!=NULL)
child->lowersibling->uppersibling=child->uppersibling;
child->parent=NULL;
child->owner=NULL;
child->lowersibling=NULL;
child->uppersibling=NULL;
return true;
}
bool OBView::RemoveSelf()
{
return false;
}
int32 OBView::CountChildren() const
{
OBView *v=topchild;
int32 children=0;
while(v!=NULL)
{
v=v->lowersibling;
children++;
}
return children;
}
OBView *OBView::ChildAt(int32 index) const
{
// We're using a tree, so traverse the tree
OBView *v=topchild;
for(int32 i=0;i<index;i++)
{
if(v==NULL)
return NULL;
v=v->lowersibling;
}
return v;
}
OBView *OBView::NextSibling() const
{
return lowersibling;
}
OBView *OBView::PreviousSibling() const
{
return uppersibling;
}
OBWindow *OBView::Window() const
{
return owner;
}
void OBView::Draw(BRect updateRect)
{
}
void OBView::MouseDown(BPoint where)
{
// Hook function
}
void OBView::MouseUp(BPoint where)
{
// Hook function
}
void OBView::MouseMoved(BPoint where,uint32 code,const BMessage *a_message)
{
// Hook function
}
void OBView::WindowActivated(bool state)
{
// Hook function
}
void OBView::KeyDown(const char *bytes, int32 numBytes)
{
// Hook function
}
void OBView::KeyUp(const char *bytes, int32 numBytes)
{
// Hook function
}
void OBView::Pulse()
{
// Hook function
}
void OBView::FrameMoved(BPoint new_position)
{
// Hook function
}
void OBView::FrameResized(float new_width, float new_height)
{
// Hook function
}
void OBView::TargetedByScrollView(BScrollView *scroll_view)
{
// Hook function
}
void OBView::BeginRectTracking(BRect startRect,uint32 style = B_TRACK_WHOLE_RECT)
{
if(!owner)
{
printf("BeginRectTracking(): view must be attached to a window\n");
return;
}
owner->serverlink->SetOpCode(BEGIN_RECT_TRACKING);
owner->serverlink->Attach(&startRect, sizeof(BRect));
owner->serverlink->Attach(&style, sizeof(uint32));
owner->serverlink->Flush();
}
void OBView::EndRectTracking(void)
{
if(!owner)
{
printf("EndRectTracking(): view must be attached to a window\n");
return;
}
owner->serverlink->SetOpCode(END_RECT_TRACKING);
owner->serverlink->Flush();
}
void OBView::GetMouse(BPoint *location, uint32 *buttons,
bool checkMessageQueue=true)
{
}
OBView *OBView::FindView(const char *name)
{
OBView *v;
v=FindViewInChildren(name);
return v;
}
OBView *OBView::Parent() const
{
return parent;
}
BRect OBView::Bounds() const
{
BRect rframe=vframe;
rframe.OffsetTo(0,0);
return rframe;
}
BRect OBView::Frame() const
{
return vframe;
}
void OBView::ConvertToScreen(BPoint* pt) const
{
}
BPoint OBView::ConvertToScreen(BPoint pt) const
{
return BPoint(-1,-1);
}
void OBView::ConvertFromScreen(BPoint* pt) const
{
}
BPoint OBView::ConvertFromScreen(BPoint pt) const
{
return BPoint(-1,-1);
}
void OBView::ConvertToScreen(BRect *r) const
{
}
BRect OBView::ConvertToScreen(BRect r) const
{
return BRect(0,0,0,0);
}
void OBView::ConvertFromScreen(BRect *r) const
{
}
BRect OBView::ConvertFromScreen(BRect r) const
{
return BRect(0,0,0,0);
}
void OBView::ConvertToParent(BPoint *pt) const
{
}
BPoint OBView::ConvertToParent(BPoint pt) const
{
return BPoint(-1,-1);
}
void OBView::ConvertFromParent(BPoint *pt) const
{
}
BPoint OBView::ConvertFromParent(BPoint pt) const
{
return BPoint(-1,-1);
}
void OBView::ConvertToParent(BRect *r) const
{
}
BRect OBView::ConvertToParent(BRect r) const
{
return BRect(0,0,0,0);
}
void OBView::ConvertFromParent(BRect *r) const
{
}
BRect OBView::ConvertFromParent(BRect r) const
{
return BRect(0,0,0,0);
}
BPoint OBView::LeftTop() const
{
return BPoint(-1,-1);
}
void OBView::GetClippingRegion(BRegion *region) const
{
}
void OBView::ConstrainClippingRegion(BRegion *region)
{
}
void OBView::SetDrawingMode(drawing_mode mode)
{
}
drawing_mode OBView::DrawingMode() const
{
return B_OP_COPY;
}
void OBView::SetBlendingMode(source_alpha srcAlpha, alpha_function alphaFunc)
{
}
void OBView::GetBlendingMode(source_alpha *srcAlpha, alpha_function *alphaFunc) const
{
}
void OBView::SetPenSize(float size)
{
}
float OBView::PenSize() const
{
return 0.0;
}
void OBView::SetViewColor(rgb_color c)
{
SET_RGB_COLOR(viewcol,c.red,c.green,c.blue,c.alpha);
owner->drawmsglink->Attach((int32)GFX_SET_VIEW_COLOR);
owner->drawmsglink->Attach((int8)c.red);
owner->drawmsglink->Attach((int8)c.green);
owner->drawmsglink->Attach((int8)c.blue);
owner->drawmsglink->Attach((int8)c.alpha);
}
void OBView::SetViewColor(uchar r, uchar g, uchar b, uchar a=255)
{
SET_RGB_COLOR(viewcol,r,g,b,a);
owner->drawmsglink->Attach((int32)GFX_SET_VIEW_COLOR);
owner->drawmsglink->Attach((int8)r);
owner->drawmsglink->Attach((int8)g);
owner->drawmsglink->Attach((int8)b);
owner->drawmsglink->Attach((int8)a);
}
rgb_color OBView::ViewColor() const
{
return viewcol;
}
void OBView::SetHighColor(rgb_color c)
{
SET_RGB_COLOR(highcol,c.red,c.green,c.blue,c.alpha);
owner->drawmsglink->Attach((int32)GFX_SET_HIGH_COLOR);
owner->drawmsglink->Attach((int8)c.red);
owner->drawmsglink->Attach((int8)c.green);
owner->drawmsglink->Attach((int8)c.blue);
owner->drawmsglink->Attach((int8)c.alpha);
}
void OBView::SetHighColor(uchar r, uchar g, uchar b, uchar a=255)
{
SET_RGB_COLOR(highcol,r,g,b,a);
owner->drawmsglink->Attach((int32)GFX_SET_HIGH_COLOR);
owner->drawmsglink->Attach((int8)r);
owner->drawmsglink->Attach((int8)g);
owner->drawmsglink->Attach((int8)b);
owner->drawmsglink->Attach((int8)a);
}
rgb_color OBView::HighColor() const
{
return highcol;
}
void OBView::SetLowColor(rgb_color c)
{
SET_RGB_COLOR(lowcol,c.red,c.green,c.blue,c.alpha);
owner->drawmsglink->Attach((int32)GFX_SET_LOW_COLOR);
owner->drawmsglink->Attach((int8)c.red);
owner->drawmsglink->Attach((int8)c.green);
owner->drawmsglink->Attach((int8)c.blue);
owner->drawmsglink->Attach((int8)c.alpha);
}
void OBView::SetLowColor(uchar r, uchar g, uchar b, uchar a=255)
{
SET_RGB_COLOR(lowcol,r,g,b,a);
owner->drawmsglink->Attach((int32)GFX_SET_LOW_COLOR);
owner->drawmsglink->Attach((int8)r);
owner->drawmsglink->Attach((int8)g);
owner->drawmsglink->Attach((int8)b);
owner->drawmsglink->Attach((int8)a);
}
rgb_color OBView::LowColor() const
{
return lowcol;
}
void OBView::SetFont(const OBFont *font, uint32 mask = B_FONT_ALL)
{
}
void OBView::GetFont(OBFont *font) const
{
}
void OBView::Invalidate(BRect invalRect)
{
if(!owner)
{
printf("Invalidate(): view must be attached to a window\n");
return;
}
owner->drawmsglink->Attach(invalRect);
}
void OBView::Invalidate(const BRegion *invalRegion)
{
// undocumented function
}
void OBView::Invalidate()
{
if(!owner)
{
printf("Invalidate(): view must be attached to a window\n");
return;
}
owner->drawmsglink->Attach(Bounds());
}
void OBView::SetFlags(uint32 flags)
{
}
uint32 OBView::Flags() const
{
return viewflags;
}
void OBView::SetResizingMode(uint32 mode)
{
}
uint32 OBView::ResizingMode() const
{
return resizeflags;
}
void OBView::MoveBy(float dh, float dv)
{
}
void OBView::MoveTo(BPoint where)
{
}
void OBView::MoveTo(float x, float y)
{
}
void OBView::ResizeBy(float dh, float dv)
{
}
void OBView::ResizeTo(float width, float height)
{
}
void OBView::MakeFocus(bool focusState = true)
{
}
bool OBView::IsFocus() const
{
return has_focus;
}
void OBView::Show()
{
hidelevel--;
for(OBView *v=topchild; v!=NULL; v=v->lowersibling )
v->Show();
}
void OBView::Hide()
{
hidelevel++;
for(OBView *v=topchild; v!=NULL; v=v->lowersibling )
v->Show();
}
bool OBView::IsHidden() const
{
return (hidelevel>0)?true:false;
}
bool OBView::IsHidden(const OBView* looking_from) const
{
// undocumented function
return false;
}
void OBView::Flush() const
{
// When attachment count inclusion is implemented, it needs to go
// in this function
owner->drawmsglink->SetOpCode(GFX_FLUSH);
owner->drawmsglink->Flush();
}
void OBView::Sync() const
{
// When attachment count inclusion is implemented, it needs to go
// in this function
int32 code;
status_t status;
ssize_t buffersize;
owner->drawmsglink->SetOpCode(GFX_SYNC);
// Reply received:
// Code: SYNC
// Attached data: none
// Buffersize: 0
owner->drawmsglink->FlushWithReply(&code,&status,&buffersize);
}
void OBView::StrokeRect(BRect r, pattern p=B_SOLID_HIGH)
{
if(!owner)
{
printf("StrokeRect(): view must be attached to a window\n");
return;
}
owner->drawmsglink->Attach((int32)GFX_STROKE_RECT);
owner->drawmsglink->Attach(r);
owner->drawmsglink->Attach(&p, sizeof(pattern));
}
void OBView::FillRect(BRect r, pattern p=B_SOLID_HIGH)
{
if(!owner)
{
printf("FillRect(): view must be attached to a window\n");
return;
}
owner->drawmsglink->Attach((int32)GFX_FILL_RECT);
owner->drawmsglink->Attach(r);
owner->drawmsglink->Attach(&p, sizeof(pattern));
}
void OBView::MovePenTo(BPoint pt)
{
if(!owner)
{
printf("MovePenTo(): view must be attached to a window\n");
return;
}
owner->drawmsglink->Attach((int32)GFX_MOVEPENTO);
owner->drawmsglink->Attach(pt);
}
void OBView::MovePenTo(float x, float y)
{
if(!owner)
{
printf("MovePenTo(): view must be attached to a window\n");
return;
}
owner->drawmsglink->Attach((int32)GFX_MOVEPENTO);
owner->drawmsglink->Attach(BPoint(x,y));
}
void OBView::MovePenBy(float x, float y)
{
if(!owner)
{
printf("MovePenBy(): view must be attached to a window\n");
return;
}
owner->drawmsglink->Attach((int32)GFX_MOVEPENBY);
owner->drawmsglink->Attach(x);
owner->drawmsglink->Attach(y);
}
BPoint OBView::PenLocation() const
{
return BPoint(0,0);
}
void OBView::StrokeLine(BPoint toPt,pattern p=B_SOLID_HIGH)
{
if(!owner)
{
printf("StrokeLine(): view must be attached to a window\n");
return;
}
owner->drawmsglink->Attach((int32)GFX_STROKE_LINE);
owner->drawmsglink->Attach(toPt);
owner->drawmsglink->Attach((pattern *)&p, sizeof(pattern));
}
void OBView::StrokeLine(BPoint pt0,BPoint pt1,pattern p=B_SOLID_HIGH)
{
if(!owner)
{
printf("StrokeLine(): view must be attached to a window\n");
return;
}
owner->drawmsglink->Attach((int32)GFX_MOVEPENTO);
owner->drawmsglink->Attach(pt0);
owner->drawmsglink->Attach((int32)GFX_STROKE_LINE);
owner->drawmsglink->Attach(pt1);
owner->drawmsglink->Attach((pattern *)&p, sizeof(pattern));
}
// Protected members
int32 OBView::GetServerToken(void)
{
// Function which asks the app_server for an ID value
// NOTE that it requires an owner
if(!owner)
{
printf("GetServerToken(): view must be attached to a window\n");
return -1;
}
int32 code;
status_t status;
ssize_t buffersize;
int32 *buffer;
owner->serverlink->SetOpCode(VIEW_GET_TOKEN);
// Reply received:
// Code: GET_VIEW_TOKEN
// Attached data:
// 1) int32 view ID
buffer=(int32*)owner->drawmsglink->FlushWithReply(&code,&status,&buffersize);
id=*buffer;
// necessary because each reply allocates memory from the heap for
// the returned buffer
delete buffer;
return id;
}
void OBView::CallAttached(OBView *view)
{
// Recursively calls AttachedToWindow() for all children of the view
AddedToWindow();
AttachedToWindow();
for(OBView *v=topchild; v!=NULL; v=v->lowersibling)
{
if(v->topchild)
CallAttached(v->topchild);
}
}
void OBView::CallDetached(OBView *view)
{
// Recursively calls DetachedFromWindow() for all children of the view
DetachedFromWindow();
for(OBView *v=topchild; v!=NULL; v=v->lowersibling)
{
if(v->topchild)
CallDetached(v->topchild);
}
}
void OBView::AddedToWindow(void)
{
// Hook function called during AddChild to take care of setup in server
// of adding a bunch of views at once, not just one
// Theoretically, shouldn't be needed, but this is here in case I do
// something really stupid. ;)
if(!owner)
return;
// If we're finally attached to a window, then the child needs to become
// known to the server
// Create View message. Layers are app_server's view counterparts
// Attach Data:
// 1) (int32) id of the parent view
// 2) (int32) id of the child view
// 3) (BRect) frame in parent's coordinates
// 4) (int32) resize flags
// 5) (int32) view flags
// 6) (uint16) view's hide level
id=GetServerToken();
PortLink *link=new PortLink(owner->outport);
link->SetOpCode(LAYER_CREATE);
link->Attach(parent->id);
link->Attach(id);
link->Attach(vframe);
link->Attach((int32)resizeflags);
link->Attach((int32)viewflags);
link->Attach(&hidelevel,sizeof(uint16));
link->Flush();
delete link;
}
OBView *OBView::FindViewInChildren(const char *name)
{
// Looks in all children of a view and returns the first view
// with a matching name.
// Process:
// 1) Search this view's children starting with topchild
// 2) If not found, cycle through them again, this second time
// recursively searching each child.
// 3) If the view is found in the first child search, assign the **
// and return the *.
// 4) If the view is found in the second child search, break out of the
// search loop by assigning and returning the *
// 5) If we complete the loop, it means that the view was not found.
// We should, thus, return NULL
return NULL;
}

View File

@ -0,0 +1,172 @@
#ifndef _OBVIEW_H_
#define _OBVIEW_H_
#include <BeBuild.h>
#include <InterfaceDefs.h>
#include <Font.h>
#include <Handler.h>
#include <Rect.h>
#include <View.h>
class BMessage;
class BString;
class BWindow;
class OBWindow;
class OBFont;
class OBView : public BHandler
{
public:
OBView( BRect frame,const char *name,uint32 resizeMask,uint32 flags);
virtual ~OBView();
virtual void AttachedToWindow();
virtual void AllAttached();
virtual void DetachedFromWindow();
virtual void AllDetached();
virtual void MessageReceived(BMessage *msg);
void AddChild(OBView *child, OBView *before = NULL);
bool RemoveChild(OBView *child);
bool RemoveSelf();
int32 CountChildren() const;
OBView *ChildAt(int32 index) const;
OBView *NextSibling() const;
OBView *PreviousSibling() const;
OBWindow *Window() const;
virtual void Draw(BRect updateRect);
virtual void MouseDown(BPoint where);
virtual void MouseUp(BPoint where);
virtual void MouseMoved( BPoint where,uint32 code,const BMessage *a_message);
virtual void WindowActivated(bool state);
virtual void KeyDown(const char *bytes, int32 numBytes);
virtual void KeyUp(const char *bytes, int32 numBytes);
virtual void Pulse();
virtual void FrameMoved(BPoint new_position);
virtual void FrameResized(float new_width, float new_height);
virtual void TargetedByScrollView(BScrollView *scroll_view);
void BeginRectTracking( BRect startRect,uint32 style = B_TRACK_WHOLE_RECT);
void EndRectTracking();
void GetMouse(BPoint *location,uint32 *buttons,bool checkMessageQueue=true);
OBView *FindView(const char *name);
OBView *Parent() const;
BRect Bounds() const;
BRect Frame() const;
void ConvertToScreen(BPoint* pt) const;
BPoint ConvertToScreen(BPoint pt) const;
void ConvertFromScreen(BPoint* pt) const;
BPoint ConvertFromScreen(BPoint pt) const;
void ConvertToScreen(BRect *r) const;
BRect ConvertToScreen(BRect r) const;
void ConvertFromScreen(BRect *r) const;
BRect ConvertFromScreen(BRect r) const;
void ConvertToParent(BPoint *pt) const;
BPoint ConvertToParent(BPoint pt) const;
void ConvertFromParent(BPoint *pt) const;
BPoint ConvertFromParent(BPoint pt) const;
void ConvertToParent(BRect *r) const;
BRect ConvertToParent(BRect r) const;
void ConvertFromParent(BRect *r) const;
BRect ConvertFromParent(BRect r) const;
BPoint LeftTop() const;
void GetClippingRegion(BRegion *region) const;
virtual void ConstrainClippingRegion(BRegion *region);
virtual void SetDrawingMode(drawing_mode mode);
drawing_mode DrawingMode() const;
void SetBlendingMode(source_alpha srcAlpha, alpha_function alphaFunc);
void GetBlendingMode(source_alpha *srcAlpha, alpha_function *alphaFunc) const;
virtual void SetPenSize(float size);
float PenSize() const;
virtual void SetViewColor(rgb_color c);
void SetViewColor(uchar r, uchar g, uchar b, uchar a = 255);
rgb_color ViewColor() const;
virtual void SetHighColor(rgb_color a_color);
void SetHighColor(uchar r, uchar g, uchar b, uchar a = 255);
rgb_color HighColor() const;
virtual void SetLowColor(rgb_color a_color);
void SetLowColor(uchar r, uchar g, uchar b, uchar a = 255);
rgb_color LowColor() const;
virtual void SetFont(const OBFont *font, uint32 mask = B_FONT_ALL);
void GetFont(OBFont *font) const;
void Invalidate(BRect invalRect);
void Invalidate(const BRegion *invalRegion);
void Invalidate();
virtual void SetFlags(uint32 flags);
uint32 Flags() const;
virtual void SetResizingMode(uint32 mode);
uint32 ResizingMode() const;
void MoveBy(float dh, float dv);
void MoveTo(BPoint where);
void MoveTo(float x, float y);
void ResizeBy(float dh, float dv);
void ResizeTo(float width, float height);
virtual void MakeFocus(bool focusState = true);
bool IsFocus() const;
virtual void Show();
virtual void Hide();
bool IsHidden() const;
bool IsHidden(const OBView* looking_from) const;
void Flush() const;
void Sync() const;
void StrokeRect(BRect r, pattern p = B_SOLID_HIGH);
void FillRect(BRect r, pattern p = B_SOLID_HIGH);
void MovePenTo(BPoint pt);
void MovePenTo(float x, float y);
void MovePenBy(float x, float y);
BPoint PenLocation() const;
void StrokeLine( BPoint toPt,pattern p = B_SOLID_HIGH);
void StrokeLine( BPoint pt0,BPoint pt1,pattern p = B_SOLID_HIGH);
protected:
friend OBWindow;
int32 GetServerToken(void);
void CallAttached(OBView *view);
void CallDetached(OBView *view);
OBView *FindViewInChildren(const char *name);
void AddedToWindow(void);
int32 id;
uint32 viewflags, resizeflags;
float origin_h;
float origin_v;
OBWindow* owner;
OBView* parent;
OBView* uppersibling;
OBView* lowersibling;
OBView* topchild;
OBView* bottomchild;
uint16 hidelevel;
bool topview;
bool has_focus;
BRect vframe;
BRegion *clipregion;
rgb_color highcol;
rgb_color lowcol;
rgb_color viewcol;
};
#endif

View File

@ -0,0 +1,523 @@
#include <Message.h>
#include <List.h>
#include <stdio.h>
#include "OBApplication.h"
#include "OBView.h"
#include "OBWindow.h"
#include "ServerProtocol.h"
#include "PortLink.h"
#define DEBUG_OBWINDOW
OBWindow::OBWindow(BRect frame,const char *title, window_type type,
uint32 flags,uint32 workspace = B_CURRENT_WORKSPACE)
{
}
OBWindow::OBWindow(BRect frame,const char *title, window_look look,window_feel feel,
uint32 flags,uint32 workspace = B_CURRENT_WORKSPACE)
{
#ifdef DEBUG_OBWINDOW
printf("OBWindow(%s)\n",title);
#endif
Lock();
// Window starts hidden by default
hidelevel=1;
wframe=frame;
wlook=look;
wfeel=feel;
wflags=flags;
wkspace=workspace;
wtitle=new BString(title);
// Receives messages from server and others
inport=create_port(50,"msgport");
if(inport==B_BAD_VALUE || inport==B_NO_MORE_PORTS)
printf("OBWindow: Couldn't create message port\n");
// Notify app that we exist
OBWindow *win=this;
PortLink *link=new PortLink(obe_app->messageport);
link->SetOpCode(ADDWINDOW);
link->Attach(&win,sizeof(OBWindow*));
link->Flush();
delete link;
// we set this flag because the window starts locked. When Show() is
// called it will unlock the looper and show the window
startlocked=true;
// We create our serverlink utilizing our application's server port
// because the server's ServerApp will handle window creation
serverlink=new PortLink(obe_app->serverport);
// make sure that the server port is valid. It will == B_NAME_NOT_FOUND if the
// OBApplication couldn't find the server
if(obe_app->serverport!=B_NAME_NOT_FOUND)
{
// Notify server of window's existence
serverlink->SetOpCode(CREATE_WINDOW);
serverlink->Attach(wframe);
serverlink->Attach((int32)WindowLookToInteger(wlook));
serverlink->Attach((int32)WindowFeelToInteger(wfeel));
serverlink->Attach((int32)wflags);
serverlink->Attach(&inport,sizeof(port_id));
serverlink->Attach((int32)wkspace);
serverlink->Attach((char*)wtitle->String(),wtitle->Length());
// Send and wait for ServerWindow port. Necessary here so we can respond to
// messages as soon as Show() is called.
int32 replycode;
status_t replystat;
ssize_t replysize;
int8 *replybuffer;
replybuffer=serverlink->FlushWithReply(&replycode,&replystat,&replysize);
outport=*((port_id*)replybuffer);
serverlink->SetPort(outport);
delete replybuffer;
#ifdef DEBUG_OBWINDOW
printf("OBWindow(%s): ServerWindow Port %ld\n",wtitle->String(),outport);
#endif
// Create and attach the top view
top_view=new OBView(wframe.OffsetToCopy(0,0),"top_view",B_FOLLOW_ALL, B_WILL_DRAW);
top_view->owner=this;
top_view->topview=true;
}
else
PostMessage(B_QUIT_REQUESTED);
}
OBWindow::~OBWindow()
{
#ifdef DEBUG_OBWINDOW
printf("~OBWindow(%s)\n",wtitle->String());
#endif
// delete all children. How? OBView recursively deletes its children
delete top_view;
delete wtitle;
delete serverlink;
delete drawmsglink;
}
void OBWindow::Quit()
{
#ifdef DEBUG_OBWINDOW
printf("%s::Quit()\n",wtitle->String());
#endif
// I hope this works. If it doesn't, we'll need to do a synchronous msg
OBWindow *win=this;
PortLink *link=new PortLink(obe_app->messageport);
link->SetOpCode(REMOVEWINDOW);
link->Attach(&win,sizeof(OBWindow *));
link->Flush();
delete link;
// Server will need to be notified of window destruction
serverlink->SetOpCode(DELETE_WINDOW);
serverlink->Attach(&ID,sizeof(int32));
serverlink->Flush();
// Quit our looper and delete our self :)
Quit();
}
void OBWindow::Close()
{
Quit();
}
void OBWindow::AddChild(OBView *child, OBView *before = NULL)
{
#ifdef DEBUG_OBWINDOW
printf("%s::AddChild()\n",wtitle->String());
#endif
top_view->AddChild(child,before);
}
bool OBWindow::RemoveChild(OBView *child)
{
#ifdef DEBUG_OBWINDOW
printf("%s::RemoveChild()\n",wtitle->String());
#endif
return top_view->RemoveChild(child);
}
int32 OBWindow::CountChildren() const
{
return top_view->CountChildren();
}
OBView *OBWindow::ChildAt(int32 index) const
{
return top_view->ChildAt(index);
}
void OBWindow::DispatchMessage(BMessage *message, BHandler *handler)
{
}
void OBWindow::MessageReceived(BMessage *message)
{
// Not sure right now what needs to be handled.
switch(message->what)
{
default:
BLooper::MessageReceived(message);
}
}
void OBWindow::FrameMoved(BPoint new_position)
{
}
void OBWindow::WorkspacesChanged(uint32 old_ws, uint32 new_ws)
{
}
void OBWindow::WorkspaceActivated(int32 ws, bool state)
{
}
void OBWindow::FrameResized(float new_width, float new_height)
{
}
void OBWindow::Minimize(bool minimize)
{
}
void OBWindow::Zoom(BPoint rec_position,float rec_width,float rec_height)
{
}
void OBWindow::Zoom()
{
}
void OBWindow::ScreenChanged(BRect screen_size, color_space depth)
{
}
bool OBWindow::NeedsUpdate() const
{
return false;
}
void OBWindow::UpdateIfNeeded()
{
}
OBView *OBWindow::FindView(const char *view_name) const
{
return top_view->FindView(view_name);
}
OBView *OBWindow::FindView(BPoint) const
{
return NULL;
}
OBView *OBWindow::CurrentFocus() const
{
return focusedview;
}
void OBWindow::Activate(bool=true)
{
}
void OBWindow::WindowActivated(bool state)
{
}
void OBWindow::ConvertToScreen(BPoint *pt) const
{
}
BPoint OBWindow::ConvertToScreen(BPoint pt) const
{
return BPoint(-1,-1);
}
void OBWindow::ConvertFromScreen(BPoint *pt) const
{
}
BPoint OBWindow::ConvertFromScreen(BPoint pt) const
{
return BPoint(-1,-1);
}
void OBWindow::ConvertToScreen(BRect *rect) const
{
}
BRect OBWindow::ConvertToScreen(BRect rect) const
{
return BRect(0,0,0,0);
}
void OBWindow::ConvertFromScreen(BRect *rect) const
{
}
BRect OBWindow::ConvertFromScreen(BRect rect) const
{
return BRect(0,0,0,0);
}
void OBWindow::MoveBy(float dx, float dy)
{
}
void OBWindow::MoveTo(BPoint)
{
}
void OBWindow::MoveTo(float x, float y)
{
}
void OBWindow::ResizeBy(float dx, float dy)
{
}
void OBWindow::ResizeTo(float width, float height)
{
}
void OBWindow::Show()
{
if(startlocked)
{
startlocked=false;
Unlock();
}
hidelevel--;
if(hidelevel==0)
{
serverlink->SetOpCode(SHOW_WINDOW);
serverlink->Flush();
}
}
void OBWindow::Hide()
{
if(hidelevel==0)
{
serverlink->SetOpCode(HIDE_WINDOW);
serverlink->Flush();
}
hidelevel++;
}
bool OBWindow::IsHidden() const
{
return false;
}
bool OBWindow::IsMinimized() const
{
return false;
}
void OBWindow::Flush() const
{
// When attachment count inclusion is implemented, it needs to go
// in this function
drawmsglink->SetOpCode(GFX_FLUSH);
drawmsglink->Flush();
}
void OBWindow::Sync() const
{
// When attachment count inclusion is implemented, it needs to go
// in this function
int32 code;
status_t status;
ssize_t buffersize;
drawmsglink->SetOpCode(GFX_SYNC);
// Reply received:
// Code: SYNC
// Attached data: none
// Buffersize: 0
drawmsglink->FlushWithReply(&code,&status,&buffersize);
}
status_t OBWindow::SendBehind(const OBWindow *window)
{
return B_ERROR;
}
void OBWindow::DisableUpdates()
{
}
void OBWindow::EnableUpdates()
{
}
void OBWindow::BeginViewTransaction()
{
}
void OBWindow::EndViewTransaction()
{
}
BRect OBWindow::Bounds() const
{
return BRect(0,0,0,0);
}
BRect OBWindow::Frame() const
{
return BRect(0,0,0,0);
}
const char *OBWindow::Title() const
{
return NULL;
}
void OBWindow::SetTitle(const char *title)
{
}
bool OBWindow::IsFront() const
{
return false;
}
bool OBWindow::IsActive() const
{
return false;
}
uint32 OBWindow::Workspaces() const
{
return 0;
}
void OBWindow::SetWorkspaces(uint32)
{
}
OBView *OBWindow::LastMouseMovedView() const
{
return NULL;
}
status_t OBWindow::AddToSubset(OBWindow *window)
{
return B_ERROR;
}
status_t OBWindow::RemoveFromSubset(OBWindow *window)
{
return B_ERROR;
}
bool OBWindow::QuitRequested()
{
return false;
}
thread_id OBWindow::Run()
{
return 0;
}
uint32 OBWindow::WindowLookToInteger(window_look wl)
{
switch(wl)
{
case B_BORDERED_WINDOW_LOOK:
return 1;
case B_TITLED_WINDOW_LOOK:
return 2;
case B_DOCUMENT_WINDOW_LOOK:
return 3;
case B_MODAL_WINDOW_LOOK:
return 4;
case B_FLOATING_WINDOW_LOOK:
return 5;
case B_NO_BORDER_WINDOW_LOOK:
default:
return 0;
}
}
uint32 OBWindow::WindowFeelToInteger(window_feel wf)
{
switch(wf)
{
case B_MODAL_SUBSET_WINDOW_FEEL:
return 1;
case B_MODAL_APP_WINDOW_FEEL:
return 2;
case B_MODAL_ALL_WINDOW_FEEL:
return 3;
case B_FLOATING_SUBSET_WINDOW_FEEL:
return 4;
case B_FLOATING_APP_WINDOW_FEEL:
return 5;
case B_FLOATING_ALL_WINDOW_FEEL:
return 6;
case B_NORMAL_WINDOW_FEEL:
default:
return 0;
}
}
window_look OBWindow::WindowLookFromType(window_type t)
{
switch(t)
{
case B_TITLED_WINDOW:
return B_TITLED_WINDOW_LOOK;
case B_DOCUMENT_WINDOW:
return B_DOCUMENT_WINDOW_LOOK;
case B_MODAL_WINDOW:
return B_MODAL_WINDOW_LOOK;
case B_FLOATING_WINDOW:
return B_FLOATING_WINDOW_LOOK;
case B_BORDERED_WINDOW:
return B_BORDERED_WINDOW_LOOK;
case B_UNTYPED_WINDOW:
default:
return B_NO_BORDER_WINDOW_LOOK;
}
}
window_feel OBWindow::WindowFeelFromType(window_type t)
{
switch(t)
{
case B_MODAL_WINDOW:
return B_MODAL_APP_WINDOW_FEEL;
case B_FLOATING_WINDOW:
return B_FLOATING_APP_WINDOW_FEEL;
// includes B_UNTYPED_WINDOW, B_BORDERED_WINDOW, B_DOCUMENT_WINDOW,
// and B_TITLED_WINDOW
default:
return B_NORMAL_WINDOW_FEEL;
}
}

View File

@ -0,0 +1,145 @@
#ifndef _OBWINDOW_H
#define _OBWINDOW_H
#include <BeBuild.h>
#include <StorageDefs.h>
#include <InterfaceDefs.h>
#include <List.h>
#include <Looper.h>
#include <Rect.h>
#include <Window.h>
#include <String.h>
class BButton;
class BMenuBar;
class BMenuItem;
class BMessage;
class BMessageRunner;
class BMessenger;
class OBView;
class PortLink;
struct message;
struct _cmd_key_;
struct _view_attr_;
#define ADDWINDOW '_adw'
#define REMOVEWINDOW '_rmw'
class OBWindow : public BLooper
{
public:
OBWindow(BRect frame,const char *title, window_type type,
uint32 flags,uint32 workspace = B_CURRENT_WORKSPACE);
OBWindow(BRect frame,const char *title, window_look look,window_feel feel,
uint32 flags,uint32 workspace = B_CURRENT_WORKSPACE);
virtual ~OBWindow();
virtual void Quit();
void Close();
void AddChild(OBView *child, OBView *before = NULL);
bool RemoveChild(OBView *child);
int32 CountChildren() const;
OBView *ChildAt(int32 index) const;
virtual void DispatchMessage(BMessage *message, BHandler *handler);
virtual void MessageReceived(BMessage *message);
virtual void FrameMoved(BPoint new_position);
virtual void WorkspacesChanged(uint32 old_ws, uint32 new_ws);
virtual void WorkspaceActivated(int32 ws, bool state);
virtual void FrameResized(float new_width, float new_height);
virtual void Minimize(bool minimize);
virtual void Zoom( BPoint rec_position,
float rec_width,
float rec_height);
void Zoom();
virtual void ScreenChanged(BRect screen_size, color_space depth);
bool NeedsUpdate() const;
void UpdateIfNeeded();
OBView *FindView(const char *view_name) const;
OBView *FindView(BPoint) const;
OBView *CurrentFocus() const;
void Activate(bool = true);
virtual void WindowActivated(bool state);
void ConvertToScreen(BPoint *pt) const;
BPoint ConvertToScreen(BPoint pt) const;
void ConvertFromScreen(BPoint *pt) const;
BPoint ConvertFromScreen(BPoint pt) const;
void ConvertToScreen(BRect *rect) const;
BRect ConvertToScreen(BRect rect) const;
void ConvertFromScreen(BRect *rect) const;
BRect ConvertFromScreen(BRect rect) const;
void MoveBy(float dx, float dy);
void MoveTo(BPoint);
void MoveTo(float x, float y);
void ResizeBy(float dx, float dy);
void ResizeTo(float width, float height);
virtual void Show();
virtual void Hide();
bool IsHidden() const;
bool IsMinimized() const;
void Flush() const;
void Sync() const;
status_t SendBehind(const OBWindow *window);
void DisableUpdates();
void EnableUpdates();
void BeginViewTransaction();
void EndViewTransaction();
BRect Bounds() const;
BRect Frame() const;
const char *Title() const;
void SetTitle(const char *title);
bool IsFront() const;
bool IsActive() const;
uint32 Workspaces() const;
void SetWorkspaces(uint32);
OBView *LastMouseMovedView() const;
status_t AddToSubset(OBWindow *window);
status_t RemoveFromSubset(OBWindow *window);
virtual bool QuitRequested();
virtual thread_id Run();
protected:
friend OBView;
uint32 WindowLookToInteger(window_look wl);
uint32 WindowFeelToInteger(window_feel wf);
window_look WindowLookFromType(window_type t);
window_feel WindowFeelFromType(window_type t);
BString *wtitle;
int32 ID;
int32 topview_ID;
uint8 hidelevel;
uint32 wflags;
PortLink *drawmsglink, *serverlink;
port_id inport;
port_id outport;
OBView *top_view;
OBView *focusedview;
OBView *fLastMouseMovedView;
BRect wframe;
window_look wlook;
window_feel wfeel;
bool startlocked;
bool in_update;
bool is_active;
int32 wkspace;
};
#endif

View File

@ -0,0 +1,438 @@
/*
PortLink.cpp:
A helper class for port-based messaging
------------------------------------------------------------------------
How it works:
The class utilizes a fixed-size array of PortLinkData object pointers. When
data is attached, a new PortLinkData object is allocated and a copy of the
passed data is created inside it. When the time comes for the message to be sent,
the data is pieced together into a flattened array and written to the port.
------------------------------------------------------------------------
Data members:
*attachments[] - fixed-size array of pointers used to hold the attached data
opcode - message value which is sent along with any data
target - port to which the message is sent when Flush() is called
replyport - port used with synchronous messaging - FlushWithReply()
bufferlength - total bytes taken up by attachments
num_attachments - internal variable which is used to track which "slot"
will be the next one to receive an attachment object
*/
#include "PortLink.h"
#include <string.h>
#include <stdio.h>
#include <malloc.h>
//#define PLDEBUG
// Internal data storage class for holding attached data whilst it is waiting
// to be Flattened() and then Flushed(). There is no need for this to be called outside
// the PortLink class.
class PortLinkData
{
public:
PortLinkData(void);
~PortLinkData(void);
bool Set(void *data, size_t size);
char *buffer;
size_t buffersize;
};
PortLink::PortLink(port_id port)
{
// For this class to be useful (and to prevent a lot of init problems)
// we require a port in the constructor
target=port;
// We start out without any data attached to the port message
num_attachments=0;
opcode=0;
bufferlength=0;
replyport=create_port(30,"PortLink reply port");
}
PortLink::~PortLink(void)
{
// If, for some odd reason, this is deleted with something attached,
// free the memory used by the attachments. We do not flush the queue
// because the port may no longer be valid in cases such as the app
// is in the process of quitting
MakeEmpty();
}
void PortLink::SetOpCode(int32 code)
{
// Sets the message code. This does not change once the message is sent.
// Another call to SetOpCode() is required for such things.
opcode=code;
}
void PortLink::SetPort(port_id port)
{
// Sets the target port. While not necessary in most uses, this exists
// mostly to prevent flexibility problems
target=port;
}
port_id PortLink::GetPort(void)
{
// Simply returns the port at which the object is pointed.
return target;
}
void PortLink::Flush(bigtime_t timeout=B_INFINITE_TIMEOUT)
{
// Fires a message off to the target, complete with attachments. NOTE:
// the recipient must delete all attachments, being the PortLink object assumes
// no responsiblity for the attachments once the message is sent.
int8 *msgbuffer;
int32 size;
if(num_attachments>0)
{
FlattenData(&msgbuffer,&size);
// Dump message to port, reset attachments, and clean up
if(timeout!=B_INFINITE_TIMEOUT)
write_port_etc(target,opcode,msgbuffer,size,B_TIMEOUT, timeout);
else
write_port(target,opcode,msgbuffer,size);
MakeEmpty();
}
else
{
if(timeout!=B_INFINITE_TIMEOUT)
write_port_etc(target,opcode,NULL,0,B_TIMEOUT, timeout);
else
write_port(target,opcode,NULL,0);
}
}
int8* PortLink::FlushWithReply(int32 *code, status_t *status, ssize_t *buffersize, bigtime_t timeout=B_INFINITE_TIMEOUT)
{
// Fires a message to the target and then waits for a reply. The target will
// receive a message with the first item being the port_id to reply to.
// NOTE: like Flush(), any attached data must be deleted.
// Effectively, an Attach() call inlined for changes
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
{
*status=B_ERROR;
return NULL;
}
// create a new storage object and stash the data
PortLinkData *pld=new PortLinkData;
if(pld->Set(&replyport,sizeof(port_id)))
{
bufferlength+=sizeof(port_id);
}
else
{
delete pld;
*status=B_ERROR;
return NULL;
}
// Flatten() inlined to make some necessary changes
int8 *buffer=new int8[bufferlength];
int8 *bufferindex=buffer;
size_t size=0;
// attach our port_id first
memcpy(bufferindex, pld->buffer, pld->buffersize);
bufferindex += pld->buffersize;
size+=pld->buffersize;
// attach everything else
for(int i=0;i<num_attachments;i++)
{
pld=attachments[i];
memcpy(bufferindex, pld->buffer, pld->buffersize);
bufferindex += pld->buffersize;
size+=pld->buffersize;
}
// Flush the thing....FOOSH! :P
write_port(target,opcode,buffer,size);
MakeEmpty();
delete buffer;
// Now we wait for the reply
if(timeout==B_INFINITE_TIMEOUT)
{
*buffersize=port_buffer_size(replyport);
if(*buffersize>0)
buffer=(int8*)new int8[*buffersize];
read_port(replyport,code, buffer, *buffersize);
}
else
{
*buffersize=port_buffer_size_etc(replyport,0,timeout);
if(*buffersize==B_TIMED_OUT)
{
*status=*buffersize;
return NULL;
}
if(*buffersize>0)
buffer=(int8*)new int8[*buffersize];
read_port(replyport,code, buffer, *buffersize);
}
// We got this far, so we apparently have some data
*status=B_OK;
return buffer;
}
void PortLink::Attach(void *data, size_t size)
{
// This is the member called to attach data to a message. Attachments are
// treated to be in 'Append' mode, tacking on each attached piece of data
// to the end of the list.
// Prevent parameter problems
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
return;
if(size==0)
return;
// create a new storage object and stash the data
PortLinkData *pld=new PortLinkData;
if(pld->Set(data,size))
{
num_attachments++;
attachments[num_attachments-1]=pld;
bufferlength+=size;
}
else
{
delete pld;
}
}
// These functions were added for a major convenience in passing common types
// Eventually, I'd like to templatize these, but for now, this'll do
void PortLink::Attach(int32 data)
{
// Prevent parameter problems
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
return;
int32 size=sizeof(int32);
// create a new storage object and stash the data
PortLinkData *pld=new PortLinkData;
if(pld->Set(&data,size))
{
num_attachments++;
attachments[num_attachments-1]=pld;
bufferlength+=size;
}
else
{
delete pld;
}
}
void PortLink::Attach(int16 data)
{
// Prevent parameter problems
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
return;
int32 size=sizeof(int16);
// create a new storage object and stash the data
PortLinkData *pld=new PortLinkData;
if(pld->Set(&data,size))
{
num_attachments++;
attachments[num_attachments-1]=pld;
bufferlength+=size;
}
else
{
delete pld;
}
}
void PortLink::Attach(int8 data)
{
// Prevent parameter problems
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
return;
int32 size=sizeof(int8);
// create a new storage object and stash the data
PortLinkData *pld=new PortLinkData;
if(pld->Set(&data,size))
{
num_attachments++;
attachments[num_attachments-1]=pld;
bufferlength+=size;
}
else
{
delete pld;
}
}
void PortLink::Attach(float data)
{
// Prevent parameter problems
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
return;
int32 size=sizeof(float);
// create a new storage object and stash the data
PortLinkData *pld=new PortLinkData;
if(pld->Set(&data,size))
{
num_attachments++;
attachments[num_attachments-1]=pld;
bufferlength+=size;
}
else
{
delete pld;
}
}
void PortLink::Attach(bool data)
{
// Prevent parameter problems
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
return;
int32 size=sizeof(bool);
// create a new storage object and stash the data
PortLinkData *pld=new PortLinkData;
if(pld->Set(&data,size))
{
num_attachments++;
attachments[num_attachments-1]=pld;
bufferlength+=size;
}
else
{
delete pld;
}
}
void PortLink::Attach(BRect data)
{
// Prevent parameter problems
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
return;
int32 size=sizeof(BRect);
// create a new storage object and stash the data
PortLinkData *pld=new PortLinkData;
if(pld->Set(&data,size))
{
num_attachments++;
attachments[num_attachments-1]=pld;
bufferlength+=size;
}
else
{
delete pld;
}
}
void PortLink::Attach(BPoint data)
{
// Prevent parameter problems
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
return;
int32 size=sizeof(BPoint);
// create a new storage object and stash the data
PortLinkData *pld=new PortLinkData;
if(pld->Set(&data,size))
{
num_attachments++;
attachments[num_attachments-1]=pld;
bufferlength+=size;
}
else
{
delete pld;
}
}
void PortLink::FlattenData(int8 **buffer,int32 *size)
{
// This function is where all the magic happens, but it is strictly internal.
// It iterates through each PortLinkData object and copies it to the main buffer
// which ends up, ultimately, being written to the PortLink's target port.
// skip if there aree no attachments
if(bufferlength<1)
return;
*buffer=new int8[bufferlength];
int8 *bufferindex=*buffer;
PortLinkData *pld;
*size=0;
for(int i=0;i<num_attachments;i++)
{
pld=attachments[i];
memcpy(bufferindex, pld->buffer, pld->buffersize);
bufferindex += pld->buffersize;
*size+=pld->buffersize;
}
}
void PortLink::MakeEmpty(void)
{
// Nukes all the attachments currently held by the PortLink class
if(num_attachments!=0)
{
for(int i=0; i<num_attachments; i++)
{
delete attachments[i];
}
}
num_attachments=0;
bufferlength=0;
}
PortLinkData::PortLinkData(void)
{
// Initialize object to empty
buffersize=0;
}
PortLinkData::~PortLinkData(void)
{
// Frees the buffer if we actually used the class to store data
if(buffersize>0)
free(buffer);
}
bool PortLinkData::Set(void *data, size_t size)
{
// Function copies the passed to the internal buffers for storage
if(size>0 && buffersize==0 && data!=NULL)
{
buffer=(char *)malloc(size);
if(buffer==NULL)
return false;
memcpy(buffer, data, size);
buffersize=size;
return true;
}
return false;
}

View File

@ -0,0 +1,43 @@
#ifndef _PORTLINK_H_
#define _PORTLINK_H_
#include <Errors.h>
#include <OS.h>
#include <SupportDefs.h>
#include <Rect.h>
#ifndef _PORTLINK_BUFFERSIZE
#define _PORTLINK_MAX_ATTACHMENTS 50
#endif
class PortLinkData;
class PortLink
{
public:
PortLink(port_id port);
~PortLink(void);
void SetOpCode(int32 code);
void SetPort(port_id port);
port_id GetPort(void);
void Flush(bigtime_t timeout=B_INFINITE_TIMEOUT);
int8* FlushWithReply(int32 *code, status_t *status, ssize_t *buffersize,
bigtime_t timeout=B_INFINITE_TIMEOUT);
void Attach(void *data, size_t size);
void Attach(int32 data);
void Attach(int16 data);
void Attach(int8 data);
void Attach(float data);
void Attach(bool data);
void Attach(BRect data);
void Attach(BPoint data);
void MakeEmpty(void);
protected:
void FlattenData(int8 **buffer,int32 *size);
port_id target, replyport;
int32 opcode, bufferlength;
int num_attachments;
PortLinkData *attachments[_PORTLINK_MAX_ATTACHMENTS];
};
#endif

View File

@ -0,0 +1,118 @@
#ifndef _APPSERVER_PROTOCOL_
#define _APPSERVER_PROTOCOL_
#define CREATE_APP 'drca'
#define DELETE_APP 'drda'
#define QUIT_APP 'srqa'
#define SET_SERVER_PORT 'srsp'
#define CREATE_WINDOW 'drcw'
#define DELETE_WINDOW 'drdw'
#define SHOW_WINDOW 'drsw'
#define HIDE_WINDOW 'drhw'
#define QUIT_WINDOW 'srqw'
#define SERVER_PORT_NAME "OBappserver"
#define SERVER_INPUT_PORT "OBinputport"
#define SERVER_FONT_LIST "/boot/home/config/settings/app_server/fontlist"
#define SERVER_SETTINGS_DIR "/boot/home/config/settings/app_server/"
// Used for quick replies from the app_server
#define SERVER_TRUE 'svtr'
#define SERVER_FALSE 'svfl'
// Font-related server communications
#define QUERY_FONTS_CHANGED 'qfch'
#define UPDATED_CLIENT_FONTLIST 'ucfl'
#define GET_FAMILY_ID 'fmid'
#define GET_STYLE_ID 'stid'
#define GET_STYLE_FOR_FACE 'stff'
// This will be modified. Currently a kludge for the input server until
// BScreens are implemented by the IK Taeam
#define GET_SCREEN_MODE 'gsmd'
#define SET_UI_COLORS 'suic'
#define GET_UI_COLOR 'guic'
#define SET_DECORATOR 'sdec'
#define GET_DECORATOR 'gdec'
#define SET_CURSOR_DATA 'sscd'
#define SET_CURSOR_BCURSOR 'sscb'
#define SET_CURSOR_BBITMAP 'sscB'
#define SHOW_CURSOR 'srsc'
#define HIDE_CURSOR 'srhc'
#define OBSCURE_CURSOR 'sroc'
#define GFX_COUNT_WORKSPACES 'gcws'
#define GFX_SET_WORKSPACE_COUNT 'ggwc'
#define GFX_CURRENT_WORKSPACE 'ggcw'
#define GFX_ACTIVATE_WORKSPACE 'gaws'
#define GFX_GET_SYSTEM_COLORS 'gsyc'
#define GFX_SET_SYSTEM_COLORS 'gsyc'
#define GFX_SET_SCREEN_MODE 'gssm'
#define GFX_GET_SCROLLBAR_INFO 'ggsi'
#define GFX_SET_SCROLLBAR_INFO 'gssi'
#define GFX_IDLE_TIME 'gidt'
#define GFX_SELECT_PRINTER_PANEL 'gspp'
#define GFX_ADD_PRINTER_PANEL 'gapp'
#define GFX_RUN_BE_ABOUT 'grba'
#define GFX_SET_FOCUS_FOLLOWS_MOUSE 'gsfm'
#define GFX_FOCUS_FOLLOWS_MOUSE 'gffm'
#define GFX_SET_HIGH_COLOR 'gshc'
#define GFX_SET_LOW_COLOR 'gslc'
#define GFX_SET_VIEW_COLOR 'gsvc'
#define GFX_STROKE_ARC 'gsar'
#define GFX_STROKE_BEZIER 'gsbz'
#define GFX_STROKE_ELLIPSE 'gsel'
#define GFX_STROKE_LINE 'gsln'
#define GFX_STROKE_POLYGON 'gspy'
#define GFX_STROKE_RECT 'gsrc'
#define GFX_STROKE_ROUNDRECT 'gsrr'
#define GFX_STROKE_SHAPE 'gssh'
#define GFX_STROKE_TRIANGLE 'gstr'
#define GFX_FILL_ARC 'gfar'
#define GFX_FILL_BEZIER 'gfbz'
#define GFX_FILL_ELLIPSE 'gfel'
#define GFX_FILL_POLYGON 'gfpy'
#define GFX_FILL_RECT 'gfrc'
#define GFX_FILL_REGION 'gfrg'
#define GFX_FILL_ROUNDRECT 'gfrr'
#define GFX_FILL_SHAPE 'gfsh'
#define GFX_FILL_TRIANGLE 'gftr'
#define GFX_MOVEPENBY 'gmpb'
#define GFX_MOVEPENTO 'gmpt'
#define GFX_SETPENSIZE 'gsps'
#define GFX_DRAW_STRING 'gdst'
#define GFX_SET_FONT 'gsft'
#define GFX_SET_FONT_SIZE 'gsfs'
#define GFX_FLUSH 'gfsh'
#define GFX_SYNC 'gsyn'
#define LAYER_CREATE 'lycr'
#define LAYER_DELETE 'lydl'
#define LAYER_ADD_CHILD 'lyac'
#define LAYER_REMOVE_CHILD 'lyrc'
#define LAYER_REMOVE_SELF 'lyrs'
#define LAYER_SHOW 'lysh'
#define LAYER_HIDE 'lyhd'
#define LAYER_MOVE 'lymv'
#define LAYER_RESIZE 'lyre'
#define LAYER_INVALIDATE 'lyin'
#define LAYER_DRAW 'lydr'
#define BEGIN_RECT_TRACKING 'rtbg'
#define END_RECT_TRACKING 'rten'
#define VIEW_GET_TOKEN 'vgtk'
#define VIEW_ADD 'vadd'
#define VIEW_REMOVE 'vrem'
#endif