diff --git a/src/servers/app/Jamfile b/src/servers/app/Jamfile index 51d4bcb9b0..df2b5d4250 100644 --- a/src/servers/app/Jamfile +++ b/src/servers/app/Jamfile @@ -1,4 +1,4 @@ SubDir OBOS_TOP src servers app ; -SubInclude OBOS_TOP src servers app proto6 ; +SubInclude OBOS_TOP src servers app proto7 ; diff --git a/src/servers/app/proto7/AppServer.cpp b/src/servers/app/proto7/AppServer.cpp new file mode 100644 index 0000000000..afe04b22ac --- /dev/null +++ b/src/servers/app/proto7/AppServer.cpp @@ -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 +#include +#include "scheduler.h" +#include +#include +#include +#include +#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;iCountItems();i++) + { + tempapp=(ServerApp *)applist->ItemAt(i); + if(tempapp!=NULL) + delete tempapp; + } + delete applist; + applist_lock->Unlock(); + +/* layerlock->Lock(); + for(i=0;iCountItems();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;iItemAt(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;iItemAt(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;iCountItems(); 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; +} diff --git a/src/servers/app/proto7/AppServer.h b/src/servers/app/proto7/AppServer.h new file mode 100644 index 0000000000..7991e86e24 --- /dev/null +++ b/src/servers/app/proto7/AppServer.h @@ -0,0 +1,51 @@ +#ifndef _OPENBEOS_APP_SERVER_H_ +#define _OPENBEOS_APP_SERVER_H_ + +#include +#include +#include +#include +//#include // 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 \ No newline at end of file diff --git a/src/servers/app/proto7/BeDecorator.cpp b/src/servers/app/proto7/BeDecorator.cpp new file mode 100644 index 0000000000..3ad08f22b0 --- /dev/null +++ b/src/servers/app/proto7/BeDecorator.cpp @@ -0,0 +1,499 @@ +#include "DisplayDriver.h" +#include +#include "LayerData.h" +#include "ColorUtils.h" +#include "BeDecorator.h" +#include "RGBColor.h" +#include "Desktop.h" + +//#define DEBUG_DECOR + +#ifdef DEBUG_DECOR +#include +#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=(titlewidthInclude(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=(wStrokeLine(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=(wStrokeLine(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); +} \ No newline at end of file diff --git a/src/servers/app/proto7/BeDecorator.h b/src/servers/app/proto7/BeDecorator.h new file mode 100644 index 0000000000..94a408e805 --- /dev/null +++ b/src/servers/app/proto7/BeDecorator.h @@ -0,0 +1,44 @@ +#ifndef _BEOS_DECORATOR_H_ +#define _BEOS_DECORATOR_H_ + +#include +#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 \ No newline at end of file diff --git a/src/servers/app/proto7/ColorSet.cpp b/src/servers/app/proto7/ColorSet.cpp new file mode 100644 index 0000000000..e0064a0eca --- /dev/null +++ b/src/servers/app/proto7/ColorSet.cpp @@ -0,0 +1,87 @@ +#include +#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(); +} diff --git a/src/servers/app/proto7/ColorUtils.cc b/src/servers/app/proto7/ColorUtils.cc new file mode 100644 index 0000000000..510476eca9 --- /dev/null +++ b/src/servers/app/proto7/ColorUtils.cc @@ -0,0 +1,101 @@ +#include "ColorUtils.h" +#include +#include + +//#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(delta1) + 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; +} diff --git a/src/servers/app/proto7/ColorUtils.h b/src/servers/app/proto7/ColorUtils.h new file mode 100644 index 0000000000..c4002d2357 --- /dev/null +++ b/src/servers/app/proto7/ColorUtils.h @@ -0,0 +1,20 @@ +#ifndef COLORUTILS_H_ +#define COLORUTILS_H_ + +#include + +// 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 \ No newline at end of file diff --git a/src/servers/app/proto7/DebugTools.cpp b/src/servers/app/proto7/DebugTools.cpp new file mode 100644 index 0000000000..f626e927be --- /dev/null +++ b/src/servers/app/proto7/DebugTools.cpp @@ -0,0 +1,222 @@ +#include +#include +#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)) ); +} + diff --git a/src/servers/app/proto7/DebugTools.h b/src/servers/app/proto7/DebugTools.h new file mode 100644 index 0000000000..55bf1b0635 --- /dev/null +++ b/src/servers/app/proto7/DebugTools.h @@ -0,0 +1,13 @@ +#ifndef _DEBUGTOOLS_H_ +#define _DEBUGTOOLS_H_ + +#include +#include +#include + +void PrintColorSpaceToStream(color_space value); +void TranslateMessageCodeToStream(int32 code); +void PrintMessageCode(int32 code); +BString TranslateStatusToString(status_t value); + +#endif \ No newline at end of file diff --git a/src/servers/app/proto7/Decorator.cpp b/src/servers/app/proto7/Decorator.cpp new file mode 100644 index 0000000000..eadb95dc59 --- /dev/null +++ b/src/servers/app/proto7/Decorator.cpp @@ -0,0 +1,242 @@ +#include "Decorator.h" +#include + +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; +} + diff --git a/src/servers/app/proto7/Decorator.h b/src/servers/app/proto7/Decorator.h new file mode 100644 index 0000000000..efe014807e --- /dev/null +++ b/src/servers/app/proto7/Decorator.h @@ -0,0 +1,121 @@ +#ifndef _DECORATOR_H_ +#define _DECORATOR_H_ + +#include +#include +#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 diff --git a/src/servers/app/proto7/Desktop.cpp b/src/servers/app/proto7/Desktop.cpp new file mode 100644 index 0000000000..c94f848a66 --- /dev/null +++ b/src/servers/app/proto7/Desktop.cpp @@ -0,0 +1,610 @@ +/* + Desktop.cpp: + Code necessary to handle the Desktop, defined as the collection of workspaces. +*/ + +//#define DEBUG_WORKSPACES + +#include +#include +#include +#include +#include +#include +#include +#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; iAddItem(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;iItemAt(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(countItemAt(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;iAddItem(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 \ No newline at end of file diff --git a/src/servers/app/proto7/Desktop.h b/src/servers/app/proto7/Desktop.h new file mode 100644 index 0000000000..4e637e9ba9 --- /dev/null +++ b/src/servers/app/proto7/Desktop.h @@ -0,0 +1,55 @@ +#ifndef _OBDESKTOP_H_ +#define _OBDESKTOP_H_ + + +#include +#include +#include + +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 \ No newline at end of file diff --git a/src/servers/app/proto7/DisplayDriver.cpp b/src/servers/app/proto7/DisplayDriver.cpp new file mode 100644 index 0000000000..519e3dc1e9 --- /dev/null +++ b/src/servers/app/proto7/DisplayDriver.cpp @@ -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) {} diff --git a/src/servers/app/proto7/DisplayDriver.h b/src/servers/app/proto7/DisplayDriver.h new file mode 100644 index 0000000000..652df6dce3 --- /dev/null +++ b/src/servers/app/proto7/DisplayDriver.h @@ -0,0 +1,131 @@ +#ifndef _DISPLAY_DRIVER_H_ +#define _DISPLAY_DRIVER_H_ + +#include +#include +#include + +#include +#include +#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 \ No newline at end of file diff --git a/src/servers/app/proto7/FontFamily.cpp b/src/servers/app/proto7/FontFamily.cpp new file mode 100644 index 0000000000..dc64f24e44 --- /dev/null +++ b/src/servers/app/proto7/FontFamily.cpp @@ -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; iCountItems(); 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; iItemAt(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; iItemAt(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; iItemAt(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; iItemAt(i); + if(fs && fs->name->Compare(style)==0) + return fs; + } + return NULL; +} diff --git a/src/servers/app/proto7/FontFamily.h b/src/servers/app/proto7/FontFamily.h new file mode 100644 index 0000000000..3a566b2a3e --- /dev/null +++ b/src/servers/app/proto7/FontFamily.h @@ -0,0 +1,81 @@ +#ifndef FONT_FAMILY_H_ +#define FONT_FAMILY_H_ + +#include +#include +#include +#include +#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 \ No newline at end of file diff --git a/src/servers/app/proto7/FontInstance.h b/src/servers/app/proto7/FontInstance.h new file mode 100644 index 0000000000..5d0007641b --- /dev/null +++ b/src/servers/app/proto7/FontInstance.h @@ -0,0 +1,53 @@ +#ifndef FONTINSTANCE_H_ +#define FONTINSTANCE_H_ + +class FontStyle; + +#include + +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 \ No newline at end of file diff --git a/src/servers/app/proto7/FontServer.h b/src/servers/app/proto7/FontServer.h new file mode 100644 index 0000000000..f856b132b4 --- /dev/null +++ b/src/servers/app/proto7/FontServer.h @@ -0,0 +1,52 @@ +#ifndef FONTSERVER_H_ +#define FONTSERVER_H_ + +#include +#include +#include +#include +#include +#include + +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 \ No newline at end of file diff --git a/src/servers/app/proto7/Globals.h b/src/servers/app/proto7/Globals.h new file mode 100644 index 0000000000..2753cad1aa --- /dev/null +++ b/src/servers/app/proto7/Globals.h @@ -0,0 +1,7 @@ +#ifndef _SERVER_GLOBALS_H_ +#define _SERVER_GLOBALS_H_ + +#include +BList *gBitmaplist, *gLayerlist; + +#endif \ No newline at end of file diff --git a/src/servers/app/proto7/Jamfile b/src/servers/app/proto7/Jamfile new file mode 100644 index 0000000000..a10960f8b3 --- /dev/null +++ b/src/servers/app/proto7/Jamfile @@ -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 ; + diff --git a/src/servers/app/proto7/Layer.cpp b/src/servers/app/proto7/Layer.cpp new file mode 100644 index 0000000000..027ca2e39e --- /dev/null +++ b/src/servers/app/proto7/Layer.cpp @@ -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 +#include +#include +#include +#include + +//#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(®ion)); + + for(i=0;iCountRects();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(®); + 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; iCountRects();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; iCountRects();i++) + newreg.Include(ConvertFromParent(reg->RectAt(i))); + return BRegion(newreg); +} + +// Tested +BRegion Layer::ConvertToTop(BRegion *reg) +{ + BRegion newreg; + for(int32 i=0; iCountRects();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; iCountRects();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; +} diff --git a/src/servers/app/proto7/Layer.h b/src/servers/app/proto7/Layer.h new file mode 100644 index 0000000000..8e57b3fb70 --- /dev/null +++ b/src/servers/app/proto7/Layer.h @@ -0,0 +1,110 @@ +#ifndef _LAYER_H_ +#define _LAYER_H_ + +#include +#include +#include +#include +#include +#include +#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 \ No newline at end of file diff --git a/src/servers/app/proto7/LayerData.h b/src/servers/app/proto7/LayerData.h new file mode 100644 index 0000000000..daf2503ae9 --- /dev/null +++ b/src/servers/app/proto7/LayerData.h @@ -0,0 +1,50 @@ +#ifndef LAYERDATA_H_ +#define LAYERDATA_H_ + +#include +#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 \ No newline at end of file diff --git a/src/servers/app/proto7/LineCalc.cpp b/src/servers/app/proto7/LineCalc.cpp new file mode 100644 index 0000000000..3e2742d2c1 --- /dev/null +++ b/src/servers/app/proto7/LineCalc.cpp @@ -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 ); +} + diff --git a/src/servers/app/proto7/LineCalc.h b/src/servers/app/proto7/LineCalc.h new file mode 100644 index 0000000000..82d3ed86ad --- /dev/null +++ b/src/servers/app/proto7/LineCalc.h @@ -0,0 +1,20 @@ +#ifndef LINECALC_H_ +#define LINECALC_H_ + +#include + +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 \ No newline at end of file diff --git a/src/servers/app/proto7/PortLink.cpp b/src/servers/app/proto7/PortLink.cpp new file mode 100644 index 0000000000..8fba724569 --- /dev/null +++ b/src/servers/app/proto7/PortLink.cpp @@ -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 +#include +#include + +//#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;ibuffer, 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;ibuffer, 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; i0) + 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; +} diff --git a/src/servers/app/proto7/PortLink.h b/src/servers/app/proto7/PortLink.h new file mode 100644 index 0000000000..9f5432daab --- /dev/null +++ b/src/servers/app/proto7/PortLink.h @@ -0,0 +1,43 @@ +#ifndef _PORTLINK_H_ +#define _PORTLINK_H_ + +#include +#include +#include +#include + +#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 \ No newline at end of file diff --git a/src/servers/app/proto7/RGBColor.cpp b/src/servers/app/proto7/RGBColor.cpp new file mode 100644 index 0000000000..a760362007 --- /dev/null +++ b/src/servers/app/proto7/RGBColor.cpp @@ -0,0 +1,176 @@ +/* + RGBColor.cpp + Color encapsulation class for app_server. +*/ + +#include +#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); +} diff --git a/src/servers/app/proto7/RGBColor.h b/src/servers/app/proto7/RGBColor.h new file mode 100644 index 0000000000..fde6854a2a --- /dev/null +++ b/src/servers/app/proto7/RGBColor.h @@ -0,0 +1,35 @@ +#ifndef RGBCOLOR_H_ +#define RGBCOLOR_H_ + +#include + +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 \ No newline at end of file diff --git a/src/servers/app/proto7/ScreenDriver.cpp b/src/servers/app/proto7/ScreenDriver.cpp new file mode 100644 index 0000000000..aebd5a5843 --- /dev/null +++ b/src/servers/app/proto7/ScreenDriver.cpp @@ -0,0 +1,1295 @@ +/* + ScreenDriver.cpp + Replacement class for the ViewDriver which utilizes a BWindowScreen for ease + of testing without requiring a second video card for SecondDriver and also + without the limitations (mostly speed) of ViewDriver. + + Note that unlike ViewDriver, this graphics module does NOT emulate + the Input Server. The Router input server filter is required for use. + + The concept is pretty close to the retooled ViewDriver, where each module + call locks a couple BLockers and draws to the buffer. + + Components: + ScreenDriver: actual driver module + FrameBuffer: BWindowScreen derivative which provides the module access + to the video card + Internal functions for doing graphics on the buffer +*/ +#include "ScreenDriver.h" +#include "ServerProtocol.h" +#include "ServerBitmap.h" +#include "SystemPalette.h" +#include "ColorUtils.h" +#include "PortLink.h" +#include "RGBColor.h" +#include "DebugTools.h" +#include "LayerData.h" +#include "LineCalc.h" +#include +#include +#include +#include + +//#define DEBUG_DRIVER +#define DEBUG_SERVER_EMU + +//#define DISABLE_SERVER_EMU + +// Define this if you want to use the spacebar to launch the server prototype's +// test application +//#define LAUNCH_TESTAPP + +#ifdef LAUNCH_TESTAPP +#include +#include +#endif + +void HLine_32Bit(graphics_card_info i, uint16 x, uint16 y, uint16 length, rgb_color col); +void HLine_16Bit(graphics_card_info i, uint16 x, uint16 y, uint16 length, uint16 col); +void HLine_16Bit(graphics_card_info i, uint16 x, uint16 y, uint16 length, uint8 col); + +FrameBuffer::FrameBuffer(const char *title, uint32 space, status_t *st,bool debug) + : BWindowScreen(title,space,st,debug) +{ + is_connected=false; + port_id serverport=find_port(SERVER_INPUT_PORT); + serverlink=new PortLink(serverport); + mousepos.Set(0,0); +#ifdef DEBUG_SERVER_EMU +printf("ScreenDriver:: app_server input port: %ld\n",serverlink->GetPort()); +#endif +} + +FrameBuffer::~FrameBuffer(void) +{ + delete serverlink; +} + +void FrameBuffer::ScreenConnected(bool connected) +{ + is_connected=connected; + if(connected) + { + // Cache the state just in case + graphics_card_info *info=CardInfo(); + gcinfo=*info; + } +} + +void FrameBuffer::MessageReceived(BMessage *msg) +{ + switch(msg->what) + { + case B_KEY_DOWN: + { + int32 key,modifiers; + msg->FindInt32("key",&key); + msg->FindInt32("modifiers",&modifiers); + + switch(key) + { + case 0x47: // Enter key + { + port_id serverport=find_port(SERVER_PORT_NAME); + write_port(serverport,B_QUIT_REQUESTED,NULL,0); + break; + } +#ifdef LAUNCH_TESTAPP + // use spacebar to launch test app + case 0x5e: + { + printf("Launching test app\n"); + status_t value; + BEntry entry("/boot/home/Desktop/openbeos/sources/proto6/OBApplication/OBApplication"); + entry_ref ref; + entry.GetRef(&ref); + value=be_roster->Launch(&ref); + + BString str=TranslateStatusToString(value); + printf("Launch return code: %s",str.String()); + printf("\n"); + break; + } +#endif + +#ifndef DISABLE_SERVER_EMU + case 0x57: // up arrow + { + // 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 + + + if(mousepos.y<=0) + { + mousepos.y=0; + break; + } + + uint32 clicks=1; // can't get the # of clicks without a *lot* of extra work :( + int64 time=(int64)real_time_clock(); + + if(modifiers & B_SHIFT_KEY) + mousepos.y--; + else + { + mousepos.y-=10; + if(mousepos.y<0) + mousepos.y=0; + } + + serverlink->SetOpCode(B_MOUSE_MOVED); + serverlink->Attach(&time, sizeof(int64)); + serverlink->Attach(&mousepos.x,sizeof(float)); + serverlink->Attach(&mousepos.y,sizeof(float)); + serverlink->Attach(&modifiers, sizeof(uint32)); + serverlink->Attach(&buttons, sizeof(uint32)); + serverlink->Attach(&clicks, sizeof(uint32)); + serverlink->Flush(); + break; + } + case 0x62: // down arrow + { + // 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 + + + if(mousepos.y>= (gcinfo.height-1)) + { + mousepos.y=gcinfo.height-1; + break; + } + + uint32 clicks=1; // can't get the # of clicks without a *lot* of extra work :( + int64 time=(int64)real_time_clock(); + + if(modifiers & B_SHIFT_KEY) + mousepos.y++; + else + { + mousepos.y+=10; + if(mousepos.y>gcinfo.height-1) + mousepos.y=gcinfo.height-1; + } + + serverlink->SetOpCode(B_MOUSE_MOVED); + serverlink->Attach(&time, sizeof(int64)); + serverlink->Attach(&mousepos.x,sizeof(float)); + serverlink->Attach(&mousepos.y,sizeof(float)); + serverlink->Attach(&modifiers, sizeof(uint32)); + serverlink->Attach(&buttons, sizeof(uint32)); + serverlink->Attach(&clicks, sizeof(uint32)); + serverlink->Flush(); + break; + } + case 0x61: // left arrow + { + // 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 + + + if(mousepos.x<=0) + { + mousepos.x=0; + break; + } + + uint32 clicks=1; // can't get the # of clicks without a *lot* of extra work :( + int64 time=(int64)real_time_clock(); + + if(modifiers & B_SHIFT_KEY) + mousepos.x--; + else + { + mousepos.x-=10; + if(mousepos.x<0) + mousepos.x=0; + } + + serverlink->SetOpCode(B_MOUSE_MOVED); + serverlink->Attach(&time, sizeof(int64)); + serverlink->Attach(&mousepos.x,sizeof(float)); + serverlink->Attach(&mousepos.y,sizeof(float)); + serverlink->Attach(&modifiers, sizeof(uint32)); + serverlink->Attach(&buttons, sizeof(uint32)); + serverlink->Attach(&clicks, sizeof(uint32)); + serverlink->Flush(); + break; + } + case 0x63: // right arrow + { + // 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 + + + if(mousepos.x>= (gcinfo.width-1)) + { + mousepos.x=gcinfo.width-1; + break; + } + + uint32 clicks=1; // can't get the # of clicks without a *lot* of extra work :( + int64 time=(int64)real_time_clock(); + + if(modifiers & B_SHIFT_KEY) + mousepos.x++; + else + { + mousepos.x+=10; + if(mousepos.x>gcinfo.width-1) + mousepos.x=gcinfo.width-1; + } + + serverlink->SetOpCode(B_MOUSE_MOVED); + serverlink->Attach(&time, sizeof(int64)); + serverlink->Attach(&mousepos.x,sizeof(float)); + serverlink->Attach(&mousepos.y,sizeof(float)); + serverlink->Attach(&modifiers, sizeof(uint32)); + serverlink->Attach(&buttons, sizeof(uint32)); + serverlink->Attach(&clicks, sizeof(uint32)); + serverlink->Flush(); + break; + } +#endif // end server emu code + default: + break; + } + + } + default: + BWindowScreen::MessageReceived(msg); + } +} + +bool FrameBuffer::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; +} + +ScreenDriver::ScreenDriver(void) +{ + status_t st; + fbuffer=new FrameBuffer("OBAppServer",B_8_BIT_640x480,&st,true); + + drawmode=DRAW_COPY; + + // We start without a cursor + cursor=NULL; + under_cursor=NULL; + + cursorframe.Set(0,0,0,0); + oldcursorframe.Set(0,0,0,0); +} + +ScreenDriver::~ScreenDriver(void) +{ + if(cursor) + delete cursor; + if(under_cursor) + delete under_cursor; +} + +bool ScreenDriver::Initialize(void) +{ + fbuffer->Show(); + + // draw on the module's default cursor here to make it look preety + + // wait 1 sec for the window to show... + snooze(500000); + return true; +} + +void ScreenDriver::Shutdown(void) +{ + fbuffer->Lock(); + fbuffer->Quit(); +} + +void ScreenDriver::DrawBitmap(ServerBitmap *bitmap, BRect source, BRect dest) +{ + Lock(); +#ifdef DEBUG_DRIVER +printf("ScreenDriver::DrawBitmap(*, (%f,%f,%f,%f),(%f,%f,%f,%f) )\n", + source.left,source.top,source.right,source.bottom, + dest.left,dest.top,dest.right,dest.bottom); +#endif + if(fbuffer->IsConnected()) + { + // Scale bitmap here if source!=dest + + switch(fbuffer->gcinfo.bits_per_pixel) + { + case 32: + case 24: + { + printf("DrawBitmap: 32/24-bit unimplemented\n"); + break; + } + case 16: + case 15: + { + printf("DrawBitmap: 16/15-bit unimplemented\n"); + break; + } + case 8: + { + printf("DrawBitmap: 8-bit unimplemented\n"); + break; + } + default: + { +#ifdef DEBUG_DRIVER +printf("Clear: unknown bit depth %u\n",fbuffer->gcinfo.bits_per_pixel); +#endif + break; + } + } + } + + Unlock(); +} + +// Ellipse code shamelessly stolen from the graphics library gd v2.0.1 and bolted on +// to support our API +void ScreenDriver::FillEllipse(BRect r, LayerData *ldata, int8 *pat) +{ + long d, b_sq, b_sq_4, b_sq_6; + long a_sq, a_sq_4, a_sq_6; + int x, y, switchem; + long lsqrt (long); + int pix, half, pstart; + int32 thick = (int32)ldata->pensize; + + half = thick / 2; + int32 w=int32(r.Width()/2), + h=int32(r.Height()/2); + int32 cx=(int32)r.left+w; + int32 cy=(int32)r.top+h; + + d = 2 * (long) h *h + (long) w *w - 2 * (long) w *w * h; + b_sq = (long) h *h; + b_sq_4 = 4 * (long) h *h; + b_sq_6 = 6 * (long) h *h; + a_sq = (long) w *w; + a_sq_4 = 4 * (long) w *w; + a_sq_6 = 6 * (long) w *w; + + x = 0; + y = -h; +// switchem = a_sq / lsqrt (a_sq + b_sq); + switchem = a_sq / (int32)sqrt(a_sq + b_sq); + + while (x <= switchem) + { + pstart = y - half; + for (pix = pstart; pix < pstart + thick; pix++) + { + Line( BPoint(cx - x, cy + pix), BPoint(cx + x, cy + pix), ldata, solidhigh); + Line( BPoint(cx - x, cy - pix), BPoint(cx + x, cy - pix), ldata, solidhigh); + } + if (d < 0) + d += b_sq_4 * x++ + b_sq_6; + else + d += b_sq_4 * x++ + b_sq_6 + a_sq_4 * (++y); + } + + /* Middlesplat! + ** Go a little further if the thickness is not nominal... + */ + if (thick > 1) + { + int xp = x; + int yp = y; + int dp = d; + int thick2 = thick + 2; + int half2 = half + 1; + + while (xp <= switchem + half) + { + pstart = yp - half2; + for (pix = pstart; pix < pstart + thick2; pix++) + { + Line( BPoint(cx - xp, cy + pix), BPoint(cx + xp, cy + pix), ldata, solidhigh); + Line( BPoint(cx - xp, cy - pix), BPoint(cx + xp, cy - pix), ldata, solidhigh); + } + if (dp < 0) + dp += b_sq_4 * xp++ + b_sq_6; + else + dp += b_sq_4 * xp++ + b_sq_6 + a_sq_4 * (++yp); + } + } + + d += -2 * (long) b_sq + 2 * (long) a_sq - 2 * (long) b_sq *(x - 1) + 2 * (long) a_sq *(y - 1); + + while (y <= 0) + { + pstart = x - half; + for (pix = pstart; pix < pstart + thick; pix++) + { + Line( BPoint(cx - pix, cy + y), BPoint(cx + pix, cy + y), ldata, solidhigh); + Line( BPoint(cx - pix, cy - y), BPoint(cx + pix, cy - y), ldata, solidhigh); + } + + if (d < 0) + d += a_sq_4 * y++ + a_sq_6 + b_sq_4 * (++x); + else + d += a_sq_4 * y++ + a_sq_6; + } +} + +void ScreenDriver::FillRect(BRect r, LayerData *d, int8 *pat) +{ +#ifdef DEBUG_DRIVER +printf("ScreenDriver::FillRect( (%f,%f,%f,%f)\n",r.left,r.top,r.right,r.bottom); +#endif + Lock(); + if(fbuffer->IsConnected()) + { + // int32 width=rect.IntegerWidth(); + for(int32 i=(int32)r.top;i<=r.bottom;i++) + // HLine(fbuffer->gcinfo,(int32)rect.left,i,width,col); + Line(BPoint(r.left,i),BPoint(r.right,i),d,pat); + } + Unlock(); +} + +void ScreenDriver::FillRoundRect(BRect r, float xrad, float yrad, LayerData *d, int8 *pat) +{ +#ifdef DEBUG_DRIVER +printf("ScreenDriver::FillRoundRect( (%f,%f,%f,%f), %llx) ---->Unimplemented<----\n",r.left,r.top, + r.right,r.bottom,*((uint64*)pat)); +#endif + FillRect(r,d,pat); +} + +void ScreenDriver::FillTriangle(BPoint *pts, BRect r, LayerData *d, int8 *pat) +{ +#ifdef DEBUG_DRIVER +printf("ScreenDriver::FillTriangle(%llx): --->Currently Unimplemented<---\n",*((uint64*)pat)); +printf("\tFirst: (%f,%f)\n\tSecond: (%f,%f)\n\tThird: (%f,%f)\n",pts[0].x,pts[0].y, + pts[1].x,pts[1].y,pts[2].x,pts[2].y); +r.PrintToStream(); +#endif + if(!pts || !d || !pat) + return; + + Lock(); + if(fbuffer->IsConnected()) + { + BPoint first, second, third; + + // Sort points according to their y values + if(pts[0].y < pts[1].y) + { + first=pts[0]; + second=pts[1]; + } + else + { + first=pts[1]; + second=pts[0]; + } + + if(second.ygcinfo.bits_per_pixel) + { + case 32: + case 24: + SetPixel32(x,y,col.GetColor32()); + break; + case 16: + case 15: + SetPixel16(x,y,col.GetColor16()); + break; + case 8: + SetPixel8(x,y,col.GetColor8()); + break; + default: + printf("Unknown pixel depth %d in SetPixel\n",fbuffer->gcinfo.bits_per_pixel); + break; + } +} + +void ScreenDriver::SetPixel32(int x, int y, rgb_color col) +{ + // Code courtesy of YNOP's SecondDriver + union + { + uint8 bytes[4]; + uint32 word; + }c1; + + c1.bytes[0]=col.blue; + c1.bytes[1]=col.green; + c1.bytes[2]=col.red; + c1.bytes[3]=col.alpha; + + uint32 *bits=(uint32*)fbuffer->gcinfo.frame_buffer; + *(bits + x + (y*fbuffer->gcinfo.width))=c1.word; +} + +void ScreenDriver::SetPixel16(int x, int y, uint16 col) +{ + +#ifdef DEBUG_DRIVER +printf("SetPixel16 unimplemented\n"); +#endif + +} + +void ScreenDriver::SetPixel8(int x, int y, uint8 col) +{ + // When the DisplayDriver API changes, we'll use the uint8 highcolor. Until then, + // we'll use *pattern + uint8 *bits=(uint8*)fbuffer->gcinfo.frame_buffer; + *(bits + x + (y*fbuffer->gcinfo.bytes_per_row))=col; + +} + +void ScreenDriver::SetMode(int32 space) +{ +#ifdef DEBUG_DRIVER +printf("ScreenDriver::SetScreen(%lu}\n",space); +#endif + Lock(); + if(fbuffer->IsConnected()) + { + fbuffer->SetSpace(space); + + // We have changed the frame buffer info, so update the cached info + graphics_card_info *info=fbuffer->CardInfo(); + fbuffer->gcinfo=*info; + + // clear the frame buffer. Otherwise, we'll have garbage in it + LayerData d; + d.highcolor.SetColor(80,85,152); + for(int32 i=0; iheight; i++) + { + Line(BPoint(0,i),BPoint(info->width-1,i),&d,solidhigh); + } + } + Unlock(); +} + +// Ellipse code shamelessly stolen from the graphics library gd v2.0.1 and bolted on +// to support our API +void ScreenDriver::StrokeEllipse(BRect r, LayerData *ldata, int8 *pat) +{ + long d, b_sq, b_sq_4, b_sq_6; + long a_sq, a_sq_4, a_sq_6; + int x, y, switchem; + long lsqrt (long); + int pix, half, pstart; + int32 thick = (int32)ldata->pensize; + + half = thick / 2; + int32 w=int32(r.Width()/2), + h=int32(r.Height()/2); + int32 cx=(int32)r.left+w; + int32 cy=(int32)r.top+h; + + d = 2 * (long) h *h + (long) w *w - 2 * (long) w *w * h; + b_sq = (long) h *h; + b_sq_4 = 4 * (long) h *h; + b_sq_6 = 6 * (long) h *h; + a_sq = (long) w *w; + a_sq_4 = 4 * (long) w *w; + a_sq_6 = 6 * (long) w *w; + + x = 0; + y = -h; +// switchem = a_sq / lsqrt (a_sq + b_sq); + switchem = a_sq / (int32)sqrt(a_sq + b_sq); + + while (x <= switchem) + { + pstart = y - half; + for (pix = pstart; pix < pstart + thick; pix++) + { + SetPixel(cx + x, cy + pix, ldata->highcolor); + SetPixel(cx - x, cy + pix, ldata->highcolor); + SetPixel(cx + x, cy - pix, ldata->highcolor); + SetPixel(cx - x, cy - pix, ldata->highcolor); + } + if (d < 0) + d += b_sq_4 * x++ + b_sq_6; + else + d += b_sq_4 * x++ + b_sq_6 + a_sq_4 * (++y); + } + + /* Middlesplat! + ** Go a little further if the thickness is not nominal... + */ + if (thick > 1) + { + int xp = x; + int yp = y; + int dp = d; + int thick2 = thick + 2; + int half2 = half + 1; + + while (xp <= switchem + half) + { + pstart = yp - half2; + for (pix = pstart; pix < pstart + thick2; pix++) + { + SetPixel(cx + xp, cy + pix, ldata->highcolor); + SetPixel(cx - xp, cy + pix, ldata->highcolor); + SetPixel(cx + xp, cy - pix, ldata->highcolor); + SetPixel(cx - xp, cy - pix, ldata->highcolor); + } + if (dp < 0) + dp += b_sq_4 * xp++ + b_sq_6; + else + dp += b_sq_4 * xp++ + b_sq_6 + a_sq_4 * (++yp); + } + } + + d += -2 * (long) b_sq + 2 * (long) a_sq - 2 * (long) b_sq *(x - 1) + 2 * (long) a_sq *(y - 1); + + while (y <= 0) + { + pstart = x - half; + for (pix = pstart; pix < pstart + thick; pix++) + { + SetPixel (cx + pix, cy + y, ldata->highcolor); + SetPixel (cx - pix, cy + y, ldata->highcolor); + SetPixel (cx + pix, cy - y, ldata->highcolor); + SetPixel (cx - pix, cy - y, ldata->highcolor); + } + + if (d < 0) + d += a_sq_4 * y++ + a_sq_6 + b_sq_4 * (++x); + else + d += a_sq_4 * y++ + a_sq_6; + } + +} + +void ScreenDriver::StrokeLine(BPoint start, BPoint end, LayerData *d, int8 *pat) +{ +#ifdef DEBUG_DRIVER +printf("ScreenDriver::StrokeLine( (%f,%f), %llx}\n",start.x,start.y,*((uint64*)pat)); +#endif + Lock(); + if(fbuffer->IsConnected()) + { + // Courtesy YNOP's SecondDriver with minor changes by DW + int oct=0; + int xoff=(int32)end.x; + int yoff=(int32)end.y; + int32 x2=(int32)start.x-xoff; + int32 y2=(int32)start.y-yoff; + int32 x1=0; + int32 y1=0; + if(y2<0){ y2=-y2; oct+=4; }//bit2=1 + if(x2<0){ x2=-x2; oct+=2;}//bit1=1 + if(x2highcolor);break; + case 1:SetPixel(( y)+xoff,( x)+yoff,d->highcolor);break; + case 3:SetPixel((-y)+xoff,( x)+yoff,d->highcolor);break; + case 2:SetPixel((-x)+xoff,( y)+yoff,d->highcolor);break; + case 6:SetPixel((-x)+xoff,(-y)+yoff,d->highcolor);break; + case 7:SetPixel((-y)+xoff,(-x)+yoff,d->highcolor);break; + case 5:SetPixel(( y)+xoff,(-x)+yoff,d->highcolor);break; + case 4:SetPixel(( x)+xoff,(-y)+yoff,d->highcolor);break; + } + x++; + sum-=Dy; + if(sum < 0) + { + y++; + sum += Dx; + } + } + } + Unlock(); +} + +void ScreenDriver::StrokePolygon(BPoint *ptlist, int32 numpts, BRect rect, LayerData *d, int8 *pat, bool is_closed=true) +{ +#ifdef DEBUG_DRIVER +printf("ScreenDriver::StrokePolygon( is_closed=%s)\n",(is_closed==true)?"true":"false"); +for(int debug=0;debugIsConnected()) + { + for(int32 i=0; i<(numpts-1); i++) + Line(ptlist[i],ptlist[i+1],d,pat); + + if(is_closed) + Line(ptlist[numpts-1],ptlist[0],d,pat); + } + Unlock(); +} + +void ScreenDriver::StrokeRect(BRect r, LayerData *d, int8 *pat) +{ +#ifdef DEBUG_DRIVER +printf("ScreenDriver::StrokeRect( (%f,%f,%f,%f), %llx)\n",r.left,r.top, + r.right,r.bottom,*((uint64*)pat)); +#endif + Lock(); + if(fbuffer->IsConnected()) + { + Line(r.LeftTop(),r.RightTop(),d,pat); + Line(r.RightTop(),r.RightBottom(),d,pat); + Line(r.RightBottom(),r.LeftBottom(),d,pat); + Line(r.LeftTop(),r.LeftBottom(),d,pat); + } + Unlock(); +} + +void ScreenDriver::StrokeRoundRect(BRect r, float xrad, float yrad, LayerData *d, int8 *pat) +{ +#ifdef DEBUG_DRIVER +printf("ScreenDriver::StrokeRoundRect( (%f,%f,%f,%f), %llx) ---->Unimplemented<----\n",r.left,r.top, + r.right,r.bottom,*((uint64*)pat)); +#endif + StrokeRect(r,d,pat); +} + +void ScreenDriver::StrokeTriangle(BPoint *pts, BRect r, LayerData *d, int8 *pat) +{ +#ifdef DEBUG_DRIVER +printf("ScreenDriver::StrokeTriangle(%llx): --->Currently Unimplemented<---\n",*((uint64*)pat)); +printf("\tFirst: (%f,%f)\n\tSecond: (%f,%f)\n\tThird: (%f,%f)\n",pts[0].x,pts[0].y, + pts[1].x,pts[1].y,pts[2].x,pts[2].y); +r.PrintToStream(); +#endif + Lock(); + if(fbuffer->IsConnected()) + { + Line(pts[0],pts[1],d,pat); + Line(pts[1],pts[2],d,pat); + Line(pts[2],pts[0],d,pat); + } + Unlock(); +} + +void ScreenDriver::SetPixelPattern(int x, int y, uint8 *pattern, uint8 patternindex) +{ + // This function is designed to add pattern support to this thing. Should be + // inlined later to add speed lost in the multiple function calls. +#ifdef DEBUG_DRIVER +printf("ScreenDriver::SetPixelPattern(%u,%u,%llx,%u)\n",x,y,*((int64*)pattern),patternindex); +#endif + if(patternindex>32) + return; + + if(fbuffer->IsConnected()) + { + uint64 *p64=(uint64*)pattern; + + // check for transparency in mask. If transparent, we can quit here + + bool transparent_bit= + ( *p64 & ~((uint64)2 << (32-patternindex)))?true:false; +printf("SetPixelPattern: pattern=0x%llx\n",*p64); +printf("SetPixelPattern: bit=0x%llx\n",((uint64)2 << (32-patternindex))); +printf("SetPixelPattern: bit mask=0x%llx\n",~((uint64)2 << (32-patternindex))); +printf("SetPixelPattern: bit value=%s\n",transparent_bit?"true":"false"); + +// bool highcolor_bit= +// ( *p64 & ~((uint64)2 << (64-patternindex)))?true:false; + + switch(fbuffer->gcinfo.bits_per_pixel) + { + case 32: + case 24: + { + + break; + } + case 16: + case 15: + { + break; + } + case 8: + { + break; + } + default: + { +#ifdef DEBUG_DRIVER +printf("SetPixelPattern: unknown bit depth %u\n",fbuffer->gcinfo.bits_per_pixel); +#endif + break; + } + } + } + else + { +#ifdef DEBUG_DRIVER +printf("SetPixelPattern: driver is disconnected\n"); +#endif + } +} + +void ScreenDriver::Line(BPoint start, BPoint end, LayerData *d, int8 *pat) +{ + // Internal function which is called from within other functions + + // Courtesy YNOP's SecondDriver with minor changes by DW + int oct=0; + int xoff=(int32)end.x; + int yoff=(int32)end.y; + int32 x2=(int32)start.x-xoff; + int32 y2=(int32)start.y-yoff; + int32 x1=0; + int32 y1=0; + if(y2<0){ y2=-y2; oct+=4; }//bit2=1 + if(x2<0){ x2=-x2; oct+=2;}//bit1=1 + if(x2highcolor);break; + case 1:SetPixel(( y)+xoff,( x)+yoff,d->highcolor);break; + case 3:SetPixel((-y)+xoff,( x)+yoff,d->highcolor);break; + case 2:SetPixel((-x)+xoff,( y)+yoff,d->highcolor);break; + case 6:SetPixel((-x)+xoff,(-y)+yoff,d->highcolor);break; + case 7:SetPixel((-y)+xoff,(-x)+yoff,d->highcolor);break; + case 5:SetPixel(( y)+xoff,(-x)+yoff,d->highcolor);break; + case 4:SetPixel(( x)+xoff,(-y)+yoff,d->highcolor);break; + } + x++; + sum-=Dy; + if(sum < 0) + { + y++; + sum += Dx; + } + } +} + +void ScreenDriver::HideCursor(void) +{ +#ifdef DEBUG_DRIVER +printf("ScreenDriver::HideCursor\n"); +#endif + Lock(); + if(fbuffer->IsConnected()) + { + SetCursorHidden(true); + if(CursorStateChanged()) + BlitBitmap(under_cursor,under_cursor->Bounds(),oldcursorframe); + + } + Unlock(); +} + +void ScreenDriver::MoveCursorTo(float x, float y) +{ +#ifdef DEBUG_DRIVER +printf("ScreenDriver::MoveCursorTo(%f,%f)\n",x,y); +#endif + Lock(); + if(!IsCursorHidden() && cursor) + BlitBitmap(under_cursor,under_cursor->Bounds(),cursorframe); + + oldcursorframe=cursorframe; + + // TODO: save cursorframe to under_cursor + + if(!IsCursorHidden() && cursor) + BlitBitmap(cursor,cursor->Bounds(),cursorframe); + + Unlock(); +} + +void ScreenDriver::ShowCursor(void) +{ +#ifdef DEBUG_DRIVER +printf("ScreenDriver::ShowCursor\n"); +#endif + Lock(); + if(fbuffer->IsConnected()) + { + hide_cursor--; + if(CursorStateChanged() && cursor) + BlitBitmap(cursor,cursor->Bounds(),cursorframe); + } + Unlock(); +} + +void ScreenDriver::ObscureCursor(void) +{ +#ifdef DEBUG_DRIVER +printf("ScreenDriver::ObscureCursor\n"); +#endif + Lock(); + SetCursorObscured(true); + if(!IsCursorHidden() && fbuffer->IsConnected() && under_cursor) + BlitBitmap(under_cursor,under_cursor->Bounds(),oldcursorframe); + Unlock(); +} +/* +void ScreenDriver::SetCursor(ServerBitmap *csr) +{ +#ifdef DEBUG_DRIVER +printf("ScreenDriver::SetCursor\n"); +#endif + if(!csr) + return; + + Lock(); + + // erase old if visible + if(!IsCursorHidden() && under_cursor) + BlitBitmap(under_cursor,under_cursor->Bounds(),oldcursorframe); + + if(cursor) + delete cursor; + if(under_cursor) + delete under_cursor; + + cursor=new ServerBitmap(csr); + under_cursor=new ServerBitmap(csr); + + cursorframe.right=cursorframe.left+csr->Bounds().Width(); + cursorframe.bottom=cursorframe.top+csr->Bounds().Height(); + oldcursorframe=cursorframe; + + // TODO: Save to oldcursorframe area to under_cursor + + if(!IsCursorHidden() && cursor) + BlitBitmap(cursor,cursor->Bounds(),cursorframe); + + Unlock(); +} +*/ +void ScreenDriver::HLine(int32 x1, int32 x2, int32 y, RGBColor color) +{ + // Internal function called from others in the driver + + // TODO: Implment and substitute Line() calls with HLine calls as appropriate + // elsewhere in the driver + + switch(fbuffer->gcinfo.bits_per_pixel) + { + case 32: + case 24: + break; + case 16: + case 15: + break; + default: + break; + } +} + +void HLine_32Bit(graphics_card_info i, uint16 x, uint16 y, uint16 length, rgb_color col) +{ +#ifdef DEBUG_DRIVER +printf("HLine() Unfinished\n"); +#endif + uint32 c=0,*pcolor,bytes; + + // apparently width=bytes per row + uint32 bpr=i.width; + + // ARGB order + c|=col.alpha * 0x01000000; + c|=col.red * 0x010000; + c|=col.green * 0x0100; + c|=col.blue; + +#ifdef DEBUG_DRIVER +printf("HLine color value: 0x%lx\n",c); +#endif + bytes=(uint32(x+length)>bpr)?length-((x+length)-bpr):length; + + pcolor=(uint32*)i.frame_buffer; + pcolor+=(y*bpr)+(x*4); + for(int32 i=0;ibpr)?length-((x+length)-bpr):length; + + memset(pcolor,col,bytes); +} + +void ScreenDriver::BlitBitmap(ServerBitmap *sourcebmp,BRect sourcerect, BRect destrect) +{ + // Another internal function called from other functions. + + if(!sourcebmp) + { +#ifdef DEBUG_DRIVER +printf("ScreenDriver::BlitBitmap(): NULL source bitmap\n"); +#endif + return; + } + + if(sourcebmp->bpp != fbuffer->gcinfo.bits_per_pixel) + { +#ifdef DEBUG_DRIVER +printf("ScreenDriver::BlitBitmap(): Incompatible bitmap pixel depth\n"); +#endif + return; + } + + uint8 colorspace_size=sourcebmp->BitsPerPixel(); + // First, clip source rect to destination + if(sourcerect.Width() > destrect.Width()) + sourcerect.right=sourcerect.left+destrect.Width(); + + + if(sourcerect.Height() > destrect.Height()) + sourcerect.bottom=sourcerect.top+destrect.Height(); + + + // Second, check rectangle bounds against their own bitmaps + BRect work_rect; + + work_rect.Set( sourcebmp->Bounds().left, + sourcebmp->Bounds().top, + sourcebmp->Bounds().right, + sourcebmp->Bounds().bottom ); + if( !(work_rect.Contains(sourcerect)) ) + { // something in selection must be clipped + if(sourcerect.left < 0) + sourcerect.left = 0; + if(sourcerect.right > work_rect.right) + sourcerect.right = work_rect.right; + if(sourcerect.top < 0) + sourcerect.top = 0; + if(sourcerect.bottom > work_rect.bottom) + sourcerect.bottom = work_rect.bottom; + } + + work_rect.Set( 0,0,fbuffer->gcinfo.width-1,fbuffer->gcinfo.height-1); + + if( !(work_rect.Contains(destrect)) ) + { // something in selection must be clipped + if(destrect.left < 0) + destrect.left = 0; + if(destrect.right > work_rect.right) + destrect.right = work_rect.right; + if(destrect.top < 0) + destrect.top = 0; + if(destrect.bottom > work_rect.bottom) + destrect.bottom = work_rect.bottom; + } + + // Set pointers to the actual data + uint8 *src_bits = (uint8*) sourcebmp->Bits(); + uint8 *dest_bits = (uint8*) fbuffer->gcinfo.frame_buffer; + + // Get row widths for offset looping + uint32 src_width = uint32 (sourcebmp->BytesPerRow()); + uint32 dest_width = uint32 (fbuffer->gcinfo.bytes_per_row); + + // Offset bitmap pointers to proper spot in each bitmap + src_bits += uint32 ( (sourcerect.top * src_width) + (sourcerect.left * colorspace_size) ); + dest_bits += uint32 ( (destrect.top * dest_width) + (destrect.left * colorspace_size) ); + + uint32 line_length = uint32 ((destrect.right - destrect.left)*colorspace_size); + uint32 lines = uint32 (destrect.bottom-destrect.top+1); + + for (uint32 pos_y = 0; pos_y != lines; pos_y++) + { + memcpy(dest_bits,src_bits,line_length); + + // Increment offsets + src_bits += src_width; + dest_bits += dest_width; + } +} + +void ScreenDriver::InvertRect(BRect r) +{ + Lock(); + if(fbuffer->IsConnected()) + { + if(r.top<0 || r.left<0 || + r.right>fbuffer->gcinfo.width-1 || r.bottom>fbuffer->gcinfo.height-1) + { + Unlock(); + return; + } + + switch(fbuffer->gcinfo.bits_per_pixel) + { + case 32: + case 24: + { + uint16 width=r.IntegerWidth(), height=r.IntegerHeight(); + uint32 *start=(uint32*)fbuffer->gcinfo.frame_buffer, *index; + start+=int32(r.top)*fbuffer->gcinfo.width; + start+=int32(r.left); + + for(int32 i=0;igcinfo.width); + for(int32 j=0; j +#include +#include +#include +#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 +#include +#include +#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;iCountItems();i++) + { + tempwin=(ServerWindow*)winlist->ItemAt(i); + if(tempwin) + delete tempwin; + } + winlist->MakeEmpty(); + delete winlist; + + ServerBitmap *tempbmp; + for(i=0;iCountItems();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;iCountItems();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 diff --git a/src/servers/app/proto7/ServerApp.h b/src/servers/app/proto7/ServerApp.h new file mode 100644 index 0000000000..6a53822cbf --- /dev/null +++ b/src/servers/app/proto7/ServerApp.h @@ -0,0 +1,42 @@ +#ifndef _SRVAPP_H_ +#define _SRVAPP_H_ + +#include +#include +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 \ No newline at end of file diff --git a/src/servers/app/proto7/ServerBitmap.cpp b/src/servers/app/proto7/ServerBitmap.cpp new file mode 100644 index 0000000000..9aca4698ed --- /dev/null +++ b/src/servers/app/proto7/ServerBitmap.cpp @@ -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 +#include +#include + +#include +#include "ServerBitmap.h" +#include "Desktop.h" +#include "DisplayDriver.h" + +//#define DEBUG_BITMAP + +#ifdef DEBUG_BITMAP +#include +#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 +#include +#include + +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 \ No newline at end of file diff --git a/src/servers/app/proto7/ServerCursor.cpp b/src/servers/app/proto7/ServerCursor.cpp new file mode 100644 index 0000000000..38f268648c --- /dev/null +++ b/src/servers/app/proto7/ServerCursor.cpp @@ -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 +#include + +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; i0)?'*':'.'); + + printf("\n"); + } +} diff --git a/src/servers/app/proto7/ServerCursor.h b/src/servers/app/proto7/ServerCursor.h new file mode 100644 index 0000000000..ee7d821813 --- /dev/null +++ b/src/servers/app/proto7/ServerCursor.h @@ -0,0 +1,26 @@ +#ifndef _SERVER_CURSOR_H +#define _SERVER_CURSOR_H + +#include +#include +#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 \ No newline at end of file diff --git a/src/servers/app/proto7/ServerFont.cpp b/src/servers/app/proto7/ServerFont.cpp new file mode 100644 index 0000000000..98fbce91ca --- /dev/null +++ b/src/servers/app/proto7/ServerFont.cpp @@ -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; +} + diff --git a/src/servers/app/proto7/ServerFont.h b/src/servers/app/proto7/ServerFont.h new file mode 100644 index 0000000000..ce219b84eb --- /dev/null +++ b/src/servers/app/proto7/ServerFont.h @@ -0,0 +1,56 @@ +#ifndef SERVERFONT_H_ +#define SERVERFONT_H_ + +#include +#include + +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 diff --git a/src/servers/app/proto7/ServerProtocol.h b/src/servers/app/proto7/ServerProtocol.h new file mode 100644 index 0000000000..7e639be15c --- /dev/null +++ b/src/servers/app/proto7/ServerProtocol.h @@ -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 \ No newline at end of file diff --git a/src/servers/app/proto7/ServerWindow.cpp b/src/servers/app/proto7/ServerWindow.cpp new file mode 100644 index 0000000000..677abdc575 --- /dev/null +++ b/src/servers/app/proto7/ServerWindow.cpp @@ -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 +#include +#include +#include +#include +#include // 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); +} diff --git a/src/servers/app/proto7/ServerWindow.h b/src/servers/app/proto7/ServerWindow.h new file mode 100644 index 0000000000..9266979aea --- /dev/null +++ b/src/servers/app/proto7/ServerWindow.h @@ -0,0 +1,76 @@ +#ifndef _SERVERWIN_H_ +#define _SERVERWIN_H_ + +#include +#include +#include +#include +#include +#include + +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 diff --git a/src/servers/app/proto7/SharedObject.h b/src/servers/app/proto7/SharedObject.h new file mode 100644 index 0000000000..db9ebf33aa --- /dev/null +++ b/src/servers/app/proto7/SharedObject.h @@ -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 + +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 \ No newline at end of file diff --git a/src/servers/app/proto7/SystemPalette.cpp b/src/servers/app/proto7/SystemPalette.cpp new file mode 100644 index 0000000000..5d81cd4155 --- /dev/null +++ b/src/servers/app/proto7/SystemPalette.cpp @@ -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; + } + +} diff --git a/src/servers/app/proto7/ViewDriver.cpp b/src/servers/app/proto7/ViewDriver.cpp new file mode 100644 index 0000000000..60b8ba1ce6 --- /dev/null +++ b/src/servers/app/proto7/ViewDriver.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include + +#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;iHeight();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;iHeight();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;iAddLine(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); + } +} diff --git a/src/servers/app/proto7/ViewDriver.h b/src/servers/app/proto7/ViewDriver.h new file mode 100644 index 0000000000..b91ea70b1e --- /dev/null +++ b/src/servers/app/proto7/ViewDriver.h @@ -0,0 +1,120 @@ +#ifndef _VIEWDRIVER_H_ +#define _VIEWDRIVER_H_ + +#include +#include +#include +#include +#include // for pattern struct +#include +#include +#include +#include +#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 \ No newline at end of file diff --git a/src/servers/app/proto7/WindowBorder.cpp b/src/servers/app/proto7/WindowBorder.cpp new file mode 100644 index 0000000000..8ff01eac02 --- /dev/null +++ b/src/servers/app/proto7/WindowBorder.cpp @@ -0,0 +1,379 @@ +#include +#include +#include +#include +#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 +#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; iCountRects();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); +} diff --git a/src/servers/app/proto7/WindowBorder.h b/src/servers/app/proto7/WindowBorder.h new file mode 100644 index 0000000000..c1090e28c0 --- /dev/null +++ b/src/servers/app/proto7/WindowBorder.h @@ -0,0 +1,40 @@ +#ifndef _WINBORDER_H_ +#define _WINBORDER_H_ + +#include +#include +#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 \ No newline at end of file diff --git a/src/servers/app/proto7/testobapp/ClientFontList.cpp b/src/servers/app/proto7/testobapp/ClientFontList.cpp new file mode 100644 index 0000000000..614929896d --- /dev/null +++ b/src/servers/app/proto7/testobapp/ClientFontList.cpp @@ -0,0 +1,367 @@ +/* + ClientFontList.cpp: + Maintainer object for the list of font families and styles which is + kept on the client side. +*/ + +#include +#include +#include +#include +#include +#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; iItemAt(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; iItemAt(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; +} + diff --git a/src/servers/app/proto7/testobapp/ClientFontList.h b/src/servers/app/proto7/testobapp/ClientFontList.h new file mode 100644 index 0000000000..0cebce656b --- /dev/null +++ b/src/servers/app/proto7/testobapp/ClientFontList.h @@ -0,0 +1,25 @@ +#ifndef CLIENT_FONT_LIST_H +#define CLIENT_FONT_LIST_H + +#include // for BFont-related definitions + +#include +#include +#include + +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 \ No newline at end of file diff --git a/src/servers/app/proto7/testobapp/DebugTools.cpp b/src/servers/app/proto7/testobapp/DebugTools.cpp new file mode 100644 index 0000000000..0a0c6aed1d --- /dev/null +++ b/src/servers/app/proto7/testobapp/DebugTools.cpp @@ -0,0 +1,219 @@ +#include +#include +#include +#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)) ); +} + diff --git a/src/servers/app/proto7/testobapp/DebugTools.h b/src/servers/app/proto7/testobapp/DebugTools.h new file mode 100644 index 0000000000..2f45b1ac6c --- /dev/null +++ b/src/servers/app/proto7/testobapp/DebugTools.h @@ -0,0 +1,12 @@ +#ifndef _DEBUGTOOLS_H_ +#define _DEBUGTOOLS_H_ + +#include +#include + +void PrintStatusToStream(status_t value); +void PrintColorSpaceToStream(color_space value); +void TranslateMessageCodeToStream(int32 code); +void PrintMessageCode(int32 code); + +#endif \ No newline at end of file diff --git a/src/servers/app/proto7/testobapp/Jamfile b/src/servers/app/proto7/testobapp/Jamfile new file mode 100644 index 0000000000..a92925a2f6 --- /dev/null +++ b/src/servers/app/proto7/testobapp/Jamfile @@ -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 ; diff --git a/src/servers/app/proto7/testobapp/OBApplication.cpp b/src/servers/app/proto7/testobapp/OBApplication.cpp new file mode 100644 index 0000000000..960646ef15 --- /dev/null +++ b/src/servers/app/proto7/testobapp/OBApplication.cpp @@ -0,0 +1,390 @@ +/* + OBApplication.cpp: + Beginning framework for a *real* BApplication replacement for the prototypes + +*/ + +#include +#include // for the pattern struct and screen mode defs +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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; iCountItems(); 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 +} diff --git a/src/servers/app/proto7/testobapp/OBApplication.h b/src/servers/app/proto7/testobapp/OBApplication.h new file mode 100644 index 0000000000..14478ddfba --- /dev/null +++ b/src/servers/app/proto7/testobapp/OBApplication.h @@ -0,0 +1,71 @@ +#ifndef _OBOS_APPLICATION_H_ +#define _OBOS_APPLICATION_H_ + +#include +#include + +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 \ No newline at end of file diff --git a/src/servers/app/proto7/testobapp/OBFont.cpp b/src/servers/app/proto7/testobapp/OBFont.cpp new file mode 100644 index 0000000000..2ddf23f994 --- /dev/null +++ b/src/servers/app/proto7/testobapp/OBFont.cpp @@ -0,0 +1,516 @@ +#include +#include +#include +#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; +} + diff --git a/src/servers/app/proto7/testobapp/OBFont.h b/src/servers/app/proto7/testobapp/OBFont.h new file mode 100644 index 0000000000..eb1d20f9d0 --- /dev/null +++ b/src/servers/app/proto7/testobapp/OBFont.h @@ -0,0 +1,189 @@ +#ifndef OBFONT_H_ +#define OBFONT_H_ + +#include +#include +#include + +#include // 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 diff --git a/src/servers/app/proto7/testobapp/OBTestApp.cpp b/src/servers/app/proto7/testobapp/OBTestApp.cpp new file mode 100644 index 0000000000..f080c86559 --- /dev/null +++ b/src/servers/app/proto7/testobapp/OBTestApp.cpp @@ -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; +} diff --git a/src/servers/app/proto7/testobapp/OBView.cpp b/src/servers/app/proto7/testobapp/OBView.cpp new file mode 100644 index 0000000000..8412aefb9a --- /dev/null +++ b/src/servers/app/proto7/testobapp/OBView.cpp @@ -0,0 +1,880 @@ +#include +#include +#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;ilowersibling; + } + + 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; +} diff --git a/src/servers/app/proto7/testobapp/OBView.h b/src/servers/app/proto7/testobapp/OBView.h new file mode 100644 index 0000000000..79aec4dfb2 --- /dev/null +++ b/src/servers/app/proto7/testobapp/OBView.h @@ -0,0 +1,172 @@ +#ifndef _OBVIEW_H_ +#define _OBVIEW_H_ + +#include +#include +#include +#include +#include +#include + +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 diff --git a/src/servers/app/proto7/testobapp/OBWindow.cpp b/src/servers/app/proto7/testobapp/OBWindow.cpp new file mode 100644 index 0000000000..0409391af1 --- /dev/null +++ b/src/servers/app/proto7/testobapp/OBWindow.cpp @@ -0,0 +1,523 @@ +#include +#include +#include +#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; + } +} diff --git a/src/servers/app/proto7/testobapp/OBWindow.h b/src/servers/app/proto7/testobapp/OBWindow.h new file mode 100644 index 0000000000..1a13dd9660 --- /dev/null +++ b/src/servers/app/proto7/testobapp/OBWindow.h @@ -0,0 +1,145 @@ +#ifndef _OBWINDOW_H +#define _OBWINDOW_H + +#include +#include +#include +#include +#include +#include +#include +#include + +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 \ No newline at end of file diff --git a/src/servers/app/proto7/testobapp/PortLink.cpp b/src/servers/app/proto7/testobapp/PortLink.cpp new file mode 100644 index 0000000000..8fba724569 --- /dev/null +++ b/src/servers/app/proto7/testobapp/PortLink.cpp @@ -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 +#include +#include + +//#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;ibuffer, 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;ibuffer, 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; i0) + 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; +} diff --git a/src/servers/app/proto7/testobapp/PortLink.h b/src/servers/app/proto7/testobapp/PortLink.h new file mode 100644 index 0000000000..9f5432daab --- /dev/null +++ b/src/servers/app/proto7/testobapp/PortLink.h @@ -0,0 +1,43 @@ +#ifndef _PORTLINK_H_ +#define _PORTLINK_H_ + +#include +#include +#include +#include + +#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 \ No newline at end of file diff --git a/src/servers/app/proto7/testobapp/ServerProtocol.h b/src/servers/app/proto7/testobapp/ServerProtocol.h new file mode 100644 index 0000000000..45e2674c0f --- /dev/null +++ b/src/servers/app/proto7/testobapp/ServerProtocol.h @@ -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 \ No newline at end of file