Added ServerApp, fully documented and 99% implemented
Made FontServer::FontsUpdated public git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2546 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
0933894bf7
commit
0934499c5d
@ -70,11 +70,11 @@ public:
|
|||||||
bool SetSystemFixed(const char *family, const char *style, float size);
|
bool SetSystemFixed(const char *family, const char *style, float size);
|
||||||
bool FontsNeedUpdated(void) { return need_update; }
|
bool FontsNeedUpdated(void) { return need_update; }
|
||||||
|
|
||||||
|
void FontsUpdated(void) { need_update=false; }
|
||||||
protected:
|
protected:
|
||||||
/*!
|
/*!
|
||||||
\brief Called when the fonts list has been updated
|
\brief Called when the fonts list has been updated
|
||||||
*/
|
*/
|
||||||
void FontsUpdated(void) { need_update=false; }
|
|
||||||
FontFamily *_FindFamily(const char *name);
|
FontFamily *_FindFamily(const char *name);
|
||||||
FT_CharMap _GetSupportedCharmap(const FT_Face &face);
|
FT_CharMap _GetSupportedCharmap(const FT_Face &face);
|
||||||
bool init;
|
bool init;
|
||||||
|
@ -2,12 +2,17 @@ SubDir OBOS_TOP src servers app server ;
|
|||||||
|
|
||||||
AddResources app_server : app_server.rsrc ;
|
AddResources app_server : app_server.rsrc ;
|
||||||
|
|
||||||
|
UsePrivateHeaders app ;
|
||||||
UseFreeTypeHeaders ;
|
UseFreeTypeHeaders ;
|
||||||
|
|
||||||
Server app_server :
|
Server app_server :
|
||||||
# Misc. Sources
|
# Misc. Sources
|
||||||
Angle.cpp
|
Angle.cpp
|
||||||
TokenHandler.cpp
|
TokenHandler.cpp
|
||||||
|
|
||||||
|
# PortLink will disappear as soon as I can figure out how to link the server
|
||||||
|
# against libopenbeos
|
||||||
|
PortLink.cpp
|
||||||
|
|
||||||
# ColorUtils will disappear as soon as I can figure out how to link the server
|
# ColorUtils will disappear as soon as I can figure out how to link the server
|
||||||
# against libopenbeos
|
# against libopenbeos
|
||||||
@ -20,6 +25,7 @@ Server app_server :
|
|||||||
# Manager Classes
|
# Manager Classes
|
||||||
AppServer.cpp
|
AppServer.cpp
|
||||||
CursorManager.cpp
|
CursorManager.cpp
|
||||||
|
ServerApp.cpp
|
||||||
|
|
||||||
# Font Classes
|
# Font Classes
|
||||||
FontFamily.cpp
|
FontFamily.cpp
|
||||||
|
757
src/servers/app/server/PortLink.cpp
Normal file
757
src/servers/app/server/PortLink.cpp
Normal file
@ -0,0 +1,757 @@
|
|||||||
|
/*
|
||||||
|
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
|
||||||
|
port_ok - flag to signal whether it's ok to send a message
|
||||||
|
capacity - contains the storage capacity of the target port.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PortLink.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
//#define PLDEBUG
|
||||||
|
//#define PLD_DEBUG
|
||||||
|
|
||||||
|
//#define CAPACITY_CHECKING
|
||||||
|
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef PLD_DEBUG
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
status_t Set(void *data, size_t size);
|
||||||
|
char *buffer;
|
||||||
|
size_t buffersize;
|
||||||
|
};
|
||||||
|
|
||||||
|
PortLink::PortLink(port_id port)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("PortLink(%lu)\n",port);
|
||||||
|
#endif
|
||||||
|
// For this class to be useful (and to prevent a lot of init problems)
|
||||||
|
// we require a port in the constructor
|
||||||
|
target=port;
|
||||||
|
port_info pi;
|
||||||
|
port_ok=(get_port_info(target,&pi)==B_OK)?true:false;
|
||||||
|
capacity=pi.capacity;
|
||||||
|
|
||||||
|
// 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");
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("\tPort valid: %s\n",(port_ok)?"true":"false");
|
||||||
|
printf("\tReply port: %lu\n",replyport);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// TODO: initialize all attachments pointers to NULL
|
||||||
|
}
|
||||||
|
|
||||||
|
PortLink::PortLink(const PortLink &link)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("PortLink(PortLink*)\n");
|
||||||
|
#endif
|
||||||
|
// The copy constructor copies everything except a PortLink's attachments. If there
|
||||||
|
// is some reason why someday I might need to change this behavior, I will, but
|
||||||
|
// for now there is no real reason I can think of.
|
||||||
|
target=link.target;
|
||||||
|
opcode=link.opcode;
|
||||||
|
port_ok=link.port_ok;
|
||||||
|
capacity=link.capacity;
|
||||||
|
bufferlength=0;
|
||||||
|
num_attachments=0;
|
||||||
|
replyport=create_port(30,"PortLink reply port");
|
||||||
|
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("\tOpcode: %lu\n",opcode);
|
||||||
|
printf("\tTarget port: %lu\n",target);
|
||||||
|
printf("\tCapacity: %lu\n",capacity);
|
||||||
|
printf("\tPort valid: %s\n",(port_ok)?"true":"false");
|
||||||
|
printf("\tReply port: %lu\n",replyport);
|
||||||
|
#endif
|
||||||
|
// TODO: initialize all attachments pointers to NULL
|
||||||
|
}
|
||||||
|
|
||||||
|
PortLink::~PortLink(void)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("~PortLink()\n");
|
||||||
|
#endif
|
||||||
|
// 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
|
||||||
|
if(num_attachments || bufferlength)
|
||||||
|
MakeEmpty();
|
||||||
|
|
||||||
|
//TODO: Inline the MakeEmpty call in a way such that it ignores num_attachments
|
||||||
|
// and deletes all non-NULL pointers, setting them to NULL afterward.
|
||||||
|
}
|
||||||
|
|
||||||
|
void PortLink::SetOpCode(int32 code)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("PortLink::SetOpCode(%c%c%c%c)\n",
|
||||||
|
(char)((code & 0xFF000000) >> 24),
|
||||||
|
(char)((code & 0x00FF0000) >> 16),
|
||||||
|
(char)((code & 0x0000FF00) >> 8),
|
||||||
|
(char)((code & 0x000000FF)) );
|
||||||
|
#endif
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("PortLink::SetPort(%lu)\n",port);
|
||||||
|
#endif
|
||||||
|
// Sets the target port. While not necessary in most uses, this exists
|
||||||
|
// mostly to prevent flexibility problems
|
||||||
|
target=port;
|
||||||
|
port_info pi;
|
||||||
|
port_ok=(get_port_info(target,&pi)==B_OK)?true:false;
|
||||||
|
capacity=pi.capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
port_id PortLink::GetPort(void)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("PortLink::GetPort() returned %lu\n",target);
|
||||||
|
#endif
|
||||||
|
// Simply returns the port at which the object is pointed.
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t PortLink::Flush(bigtime_t timeout=B_INFINITE_TIMEOUT)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("PortLink::Flush()\n");
|
||||||
|
#endif
|
||||||
|
// Fires a message off to the target, complete with attachments.
|
||||||
|
int8 *msgbuffer;
|
||||||
|
int32 size;
|
||||||
|
status_t write_stat=B_OK;
|
||||||
|
|
||||||
|
if(!port_ok)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("\tFlush(): invalid port\n");
|
||||||
|
#endif
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(num_attachments>0)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("\tFlush(): flushing %d attachments\n",num_attachments);
|
||||||
|
#endif
|
||||||
|
FlattenData(&msgbuffer,&size);
|
||||||
|
|
||||||
|
// Dump message to port, reset attachments, and clean up
|
||||||
|
if(timeout!=B_INFINITE_TIMEOUT)
|
||||||
|
write_stat=write_port_etc(target,opcode,msgbuffer,size,B_TIMEOUT, timeout);
|
||||||
|
else
|
||||||
|
write_stat=write_port(target,opcode,msgbuffer,size);
|
||||||
|
MakeEmpty();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("\tFlush(): flushing without attachments\n");
|
||||||
|
#endif
|
||||||
|
if(timeout!=B_INFINITE_TIMEOUT)
|
||||||
|
write_stat=write_port_etc(target,opcode,NULL,0,B_TIMEOUT, timeout);
|
||||||
|
else
|
||||||
|
write_stat=write_port(target,opcode,NULL,0);
|
||||||
|
}
|
||||||
|
return write_stat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int8* PortLink::FlushWithReply(int32 *code, status_t *status, ssize_t *buffersize, bigtime_t timeout=B_INFINITE_TIMEOUT)
|
||||||
|
{
|
||||||
|
// Deprecated call which functions exactly like PortLink(PortLink::ReplyData *data)
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("PortLink::FlushWithReply(int32*,status_t*,ssize_t*,bigtime_t)\n");
|
||||||
|
#endif
|
||||||
|
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("PortLink::FlushWithReply(): too many attachments\n");
|
||||||
|
#endif
|
||||||
|
*status=B_ERROR;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!port_ok)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("PortLink::FlushWithReply(): bad port\n");
|
||||||
|
#endif
|
||||||
|
*status=B_BAD_VALUE;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a new storage object and stash the data
|
||||||
|
PortLinkData *pld=new PortLinkData;
|
||||||
|
if(pld->Set(&replyport,sizeof(port_id))==B_OK)
|
||||||
|
{
|
||||||
|
bufferlength+=sizeof(port_id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete pld;
|
||||||
|
*status=B_ERROR;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flatten() inlined to make some necessary changes
|
||||||
|
int8 *buffer=new int8[bufferlength];
|
||||||
|
int8 *bufferindex=buffer;
|
||||||
|
size_t size=0;
|
||||||
|
|
||||||
|
// attach our port_id first
|
||||||
|
memcpy(bufferindex, pld->buffer, pld->buffersize);
|
||||||
|
bufferindex += pld->buffersize;
|
||||||
|
size+=pld->buffersize;
|
||||||
|
|
||||||
|
// attach everything else
|
||||||
|
for(int i=0;i<num_attachments;i++)
|
||||||
|
{
|
||||||
|
pld=attachments[i];
|
||||||
|
memcpy(bufferindex, pld->buffer, pld->buffersize);
|
||||||
|
bufferindex += pld->buffersize;
|
||||||
|
size+=pld->buffersize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush the thing....FOOSH! :P
|
||||||
|
write_port(target,opcode,buffer,size);
|
||||||
|
MakeEmpty();
|
||||||
|
delete buffer;
|
||||||
|
|
||||||
|
// Now we wait for the reply
|
||||||
|
buffer=NULL;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t PortLink::FlushWithReply(PortLink::ReplyData *data,bigtime_t timeout=B_INFINITE_TIMEOUT)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("PortLink::FlushWithReply(ReplyData*,bigtime_t)\n");
|
||||||
|
#endif
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("\tFlushWithReply(): too many attachments\n");
|
||||||
|
#endif
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!port_ok)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("\tFlushWithReply(): invalid port\n");
|
||||||
|
#endif
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a new storage object and stash the data
|
||||||
|
PortLinkData *pld=new PortLinkData;
|
||||||
|
if(pld->Set(&replyport,sizeof(port_id))==B_OK)
|
||||||
|
{
|
||||||
|
bufferlength+=sizeof(port_id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("\tFlushWithReply(): unable to assign reply port to data\n");
|
||||||
|
#endif
|
||||||
|
delete pld;
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flatten() inlined to make some necessary changes
|
||||||
|
int8 *buffer=new int8[bufferlength];
|
||||||
|
int8 *bufferindex=buffer;
|
||||||
|
size_t size=0;
|
||||||
|
|
||||||
|
// attach our port_id first
|
||||||
|
memcpy(bufferindex, pld->buffer, pld->buffersize);
|
||||||
|
bufferindex += pld->buffersize;
|
||||||
|
size+=pld->buffersize;
|
||||||
|
|
||||||
|
// attach everything else
|
||||||
|
for(int i=0;i<num_attachments;i++)
|
||||||
|
{
|
||||||
|
pld=attachments[i];
|
||||||
|
memcpy(bufferindex, pld->buffer, pld->buffersize);
|
||||||
|
bufferindex += pld->buffersize;
|
||||||
|
size+=pld->buffersize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush the thing....FOOSH! :P
|
||||||
|
write_port(target,opcode,buffer,size);
|
||||||
|
MakeEmpty();
|
||||||
|
delete buffer;
|
||||||
|
|
||||||
|
// Now we wait for the reply
|
||||||
|
if(timeout==B_INFINITE_TIMEOUT)
|
||||||
|
{
|
||||||
|
data->buffersize=port_buffer_size(replyport);
|
||||||
|
if(data->buffersize>0)
|
||||||
|
data->buffer=(int8*)new int8[data->buffersize];
|
||||||
|
read_port(replyport,&(data->code),data->buffer, data->buffersize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data->buffersize=port_buffer_size_etc(replyport,0,timeout);
|
||||||
|
if(data->buffersize==B_TIMED_OUT)
|
||||||
|
return B_TIMED_OUT;
|
||||||
|
|
||||||
|
if(data->buffersize>0)
|
||||||
|
data->buffer=(int8*)new int8[data->buffersize];
|
||||||
|
read_port(replyport,&(data->code),data->buffer, data->buffersize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We got this far, so we apparently have some data
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t PortLink::Attach(void *data, size_t size)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("Attach(%p,%ld)\n",data,size);
|
||||||
|
#endif
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("\tAttach(): too many attachments\n");
|
||||||
|
#endif
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(size==0)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("\tAttach(): size invalid -> size=0\n");
|
||||||
|
#endif
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CAPACITY_CHECKING
|
||||||
|
if(bufferlength+size>capacity)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("\tAttach(): bufferlength+size > port capacity\n");
|
||||||
|
#endif
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// create a new storage object and stash the data
|
||||||
|
PortLinkData *pld=new PortLinkData;
|
||||||
|
if(pld->Set(data,size)==B_OK)
|
||||||
|
{
|
||||||
|
num_attachments++;
|
||||||
|
attachments[num_attachments-1]=pld;
|
||||||
|
bufferlength+=size;
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("\tAttach(): successful\n");
|
||||||
|
printf("\t\tAttach(): attachments now %u\n", num_attachments);
|
||||||
|
printf("\t\tAttach(): buffer length is %lu\n", bufferlength);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("\tAttach(): Couldn't assign data to PortLinkData object\n");
|
||||||
|
#endif
|
||||||
|
delete pld;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
status_t PortLink::Attach(int32 data)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("Attach(%ld)\n",data);
|
||||||
|
#endif
|
||||||
|
// Prevent parameter problems
|
||||||
|
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
int32 size=sizeof(int32);
|
||||||
|
|
||||||
|
#ifdef CAPACITY_CHECKING
|
||||||
|
if(bufferlength+size>capacity)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// create a new storage object and stash the data
|
||||||
|
PortLinkData *pld=new PortLinkData;
|
||||||
|
if(pld->Set(&data,size)==B_OK)
|
||||||
|
{
|
||||||
|
num_attachments++;
|
||||||
|
attachments[num_attachments-1]=pld;
|
||||||
|
bufferlength+=size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete pld;
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t PortLink::Attach(int16 data)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("Attach(%d)\n",data);
|
||||||
|
#endif
|
||||||
|
// Prevent parameter problems
|
||||||
|
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
int32 size=sizeof(int16);
|
||||||
|
|
||||||
|
#ifdef CAPACITY_CHECKING
|
||||||
|
if(bufferlength+size>capacity)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// create a new storage object and stash the data
|
||||||
|
PortLinkData *pld=new PortLinkData;
|
||||||
|
if(pld->Set(&data,size)==B_OK)
|
||||||
|
{
|
||||||
|
num_attachments++;
|
||||||
|
attachments[num_attachments-1]=pld;
|
||||||
|
bufferlength+=size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete pld;
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t PortLink::Attach(int8 data)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("Attach(%d)\n",data);
|
||||||
|
#endif
|
||||||
|
// Prevent parameter problems
|
||||||
|
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
int32 size=sizeof(int8);
|
||||||
|
|
||||||
|
#ifdef CAPACITY_CHECKING
|
||||||
|
if(bufferlength+size>capacity)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// create a new storage object and stash the data
|
||||||
|
PortLinkData *pld=new PortLinkData;
|
||||||
|
if(pld->Set(&data,size)==B_OK)
|
||||||
|
{
|
||||||
|
num_attachments++;
|
||||||
|
attachments[num_attachments-1]=pld;
|
||||||
|
bufferlength+=size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete pld;
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t PortLink::Attach(float data)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("Attach(%f)\n",data);
|
||||||
|
#endif
|
||||||
|
// Prevent parameter problems
|
||||||
|
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
int32 size=sizeof(float);
|
||||||
|
|
||||||
|
#ifdef CAPACITY_CHECKING
|
||||||
|
if(bufferlength+size>capacity)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// create a new storage object and stash the data
|
||||||
|
PortLinkData *pld=new PortLinkData;
|
||||||
|
if(pld->Set(&data,size)==B_OK)
|
||||||
|
{
|
||||||
|
num_attachments++;
|
||||||
|
attachments[num_attachments-1]=pld;
|
||||||
|
bufferlength+=size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete pld;
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t PortLink::Attach(bool data)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("Attach(%s)\n",(data)?"true":"false");
|
||||||
|
#endif
|
||||||
|
// Prevent parameter problems
|
||||||
|
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
int32 size=sizeof(bool);
|
||||||
|
|
||||||
|
#ifdef CAPACITY_CHECKING
|
||||||
|
if(bufferlength+size>capacity)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// create a new storage object and stash the data
|
||||||
|
PortLinkData *pld=new PortLinkData;
|
||||||
|
if(pld->Set(&data,size)==B_OK)
|
||||||
|
{
|
||||||
|
num_attachments++;
|
||||||
|
attachments[num_attachments-1]=pld;
|
||||||
|
bufferlength+=size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete pld;
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t PortLink::Attach(BRect data)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("Attach(BRect(%f,%f,%f,%f))\n",data.left,data.top,data.right,data.bottom);
|
||||||
|
#endif
|
||||||
|
// Prevent parameter problems
|
||||||
|
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
int32 size=sizeof(BRect);
|
||||||
|
|
||||||
|
#ifdef CAPACITY_CHECKING
|
||||||
|
if(bufferlength+size>capacity)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// create a new storage object and stash the data
|
||||||
|
PortLinkData *pld=new PortLinkData;
|
||||||
|
if(pld->Set(&data,size)==B_OK)
|
||||||
|
{
|
||||||
|
num_attachments++;
|
||||||
|
attachments[num_attachments-1]=pld;
|
||||||
|
bufferlength+=size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete pld;
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t PortLink::Attach(BPoint data)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("Attach(BPoint(%f,%f))\n",data.x,data.y);
|
||||||
|
#endif
|
||||||
|
// Prevent parameter problems
|
||||||
|
if(num_attachments>=_PORTLINK_MAX_ATTACHMENTS)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
int32 size=sizeof(BPoint);
|
||||||
|
|
||||||
|
#ifdef CAPACITY_CHECKING
|
||||||
|
if(bufferlength+size>capacity)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// create a new storage object and stash the data
|
||||||
|
PortLinkData *pld=new PortLinkData;
|
||||||
|
if(pld->Set(&data,size)==B_OK)
|
||||||
|
{
|
||||||
|
num_attachments++;
|
||||||
|
attachments[num_attachments-1]=pld;
|
||||||
|
bufferlength+=size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete pld;
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("PortLink::FlattenData: bufferlength<1\n");
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*buffer=new int8[bufferlength];
|
||||||
|
int8 *bufferindex=*buffer;
|
||||||
|
PortLinkData *pld;
|
||||||
|
*size=0;
|
||||||
|
|
||||||
|
for(int i=0;i<num_attachments;i++)
|
||||||
|
{
|
||||||
|
pld=attachments[i];
|
||||||
|
memcpy(bufferindex, pld->buffer, pld->buffersize);
|
||||||
|
bufferindex += pld->buffersize;
|
||||||
|
*size+=pld->buffersize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PortLink::MakeEmpty(void)
|
||||||
|
{
|
||||||
|
#ifdef PLDEBUG
|
||||||
|
printf("PortLink::MakeEmpty\n");
|
||||||
|
#endif
|
||||||
|
// Nukes all the attachments currently held by the PortLink class
|
||||||
|
if(num_attachments!=0)
|
||||||
|
{
|
||||||
|
for(int i=0; i<num_attachments; i++)
|
||||||
|
{
|
||||||
|
delete attachments[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
num_attachments=0;
|
||||||
|
bufferlength=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PortLinkData::PortLinkData(void)
|
||||||
|
{
|
||||||
|
// Initialize object to empty
|
||||||
|
buffersize=0;
|
||||||
|
buffer=NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PortLinkData::~PortLinkData(void)
|
||||||
|
{
|
||||||
|
// Frees the buffer if we actually used the class to store data
|
||||||
|
if(buffersize>0 && buffer!=NULL)
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t PortLinkData::Set(void *data, size_t size)
|
||||||
|
{
|
||||||
|
#ifdef PLD_DEBUG
|
||||||
|
printf("PortLinkData::Set(%p,%lu)\n",data,size);
|
||||||
|
#endif
|
||||||
|
// Function copies the passed to the internal buffers for storage
|
||||||
|
if(size>0 && buffersize==0 && data!=NULL)
|
||||||
|
{
|
||||||
|
buffer=(char *)malloc(size);
|
||||||
|
if(!buffer)
|
||||||
|
{
|
||||||
|
#ifdef PLD_DEBUG
|
||||||
|
printf("\tSet(): Couldn't allocate buffer\n");
|
||||||
|
#endif
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
memcpy(buffer, data, size);
|
||||||
|
buffersize=size;
|
||||||
|
#ifdef PLD_DEBUG
|
||||||
|
printf("\tSet(): SUCCESS\n");
|
||||||
|
#endif
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PLD_DEBUG
|
||||||
|
if(size==0)
|
||||||
|
printf("\tSet(): given an invalid size\n");
|
||||||
|
if(buffersize>0)
|
||||||
|
printf("\tSet(): buffersize is nonzero\n");
|
||||||
|
if(buffersize>0)
|
||||||
|
printf("\tSet(): data is NULL\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
436
src/servers/app/server/ServerApp.cpp
Normal file
436
src/servers/app/server/ServerApp.cpp
Normal file
@ -0,0 +1,436 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2001-2002, OpenBeOS
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
// File Name: ServerApp.cpp
|
||||||
|
// Author: DarkWyrm <bpmagic@columbus.rr.com>
|
||||||
|
// Description: Server-side BApplication counterpart
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
#include <AppDefs.h>
|
||||||
|
#include <List.h>
|
||||||
|
#include <String.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <PortLink.h>
|
||||||
|
#include "CursorManager.h"
|
||||||
|
//#include "Desktop.h"
|
||||||
|
#include "DisplayDriver.h"
|
||||||
|
#include "FontServer.h"
|
||||||
|
#include "ServerApp.h"
|
||||||
|
//#include "ServerWindow.h"
|
||||||
|
#include "ServerCursor.h"
|
||||||
|
#include "ServerBitmap.h"
|
||||||
|
#include "ServerProtocol.h"
|
||||||
|
#include "ServerConfig.h"
|
||||||
|
#include "LayerData.h"
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Constructor
|
||||||
|
\param sendport port ID for the BApplication which will receive the
|
||||||
|
ServerApp's messages
|
||||||
|
\param rcvport port by which the ServerApp will receive messages from its
|
||||||
|
BApplication.
|
||||||
|
\param _signature NULL-terminated string which contains the BApplication's
|
||||||
|
MIME _signature.
|
||||||
|
*/
|
||||||
|
ServerApp::ServerApp(port_id sendport, port_id rcvport, char *signature)
|
||||||
|
{
|
||||||
|
// need to copy the _signature because the message buffer
|
||||||
|
// owns the copy which we are passed as a parameter.
|
||||||
|
_signature=(signature)?signature:"BeApplication";
|
||||||
|
|
||||||
|
// _sender is the our BApplication's event port
|
||||||
|
_sender=sendport;
|
||||||
|
_applink=new PortLink(_sender);
|
||||||
|
_applink->SetPort(_sender);
|
||||||
|
|
||||||
|
// Gotta get the team ID so we can ping the application
|
||||||
|
port_info pinfo;
|
||||||
|
get_port_info(_sender,&pinfo);
|
||||||
|
_target_id=pinfo.team;
|
||||||
|
|
||||||
|
// _receiver is the port we receive messages from our BApplication
|
||||||
|
_receiver=rcvport;
|
||||||
|
|
||||||
|
_winlist=new BList(0);
|
||||||
|
_bmplist=new BList(0);
|
||||||
|
_isactive=false;
|
||||||
|
|
||||||
|
ServerCursor *defaultc=cursormanager->GetCursor(B_CURSOR_DEFAULT);
|
||||||
|
|
||||||
|
_appcursor=(defaultc)?new ServerCursor(defaultc):NULL;
|
||||||
|
_lock=create_sem(1,"ServerApp sem");
|
||||||
|
|
||||||
|
// TODO: uncomment this and include Desktop.h when the desktop classes are done
|
||||||
|
// _driver=get_gfxdriver();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Does all necessary teardown for application
|
||||||
|
ServerApp::~ServerApp(void)
|
||||||
|
{
|
||||||
|
int32 i;
|
||||||
|
|
||||||
|
// TODO: Enable this when we have ServerWindow implemented
|
||||||
|
/* ServerWindow *tempwin;
|
||||||
|
for(i=0;i<_winlist->CountItems();i++)
|
||||||
|
{
|
||||||
|
tempwin=(ServerWindow*)_winlist->ItemAt(i);
|
||||||
|
if(tempwin)
|
||||||
|
delete tempwin;
|
||||||
|
}
|
||||||
|
_winlist->MakeEmpty();
|
||||||
|
delete _winlist;
|
||||||
|
*/
|
||||||
|
ServerBitmap *tempbmp;
|
||||||
|
for(i=0;i<_bmplist->CountItems();i++)
|
||||||
|
{
|
||||||
|
tempbmp=(ServerBitmap*)_bmplist->ItemAt(i);
|
||||||
|
if(tempbmp)
|
||||||
|
delete tempbmp;
|
||||||
|
}
|
||||||
|
_bmplist->MakeEmpty();
|
||||||
|
delete _bmplist;
|
||||||
|
|
||||||
|
delete _applink;
|
||||||
|
_applink=NULL;
|
||||||
|
if(_appcursor)
|
||||||
|
delete _appcursor;
|
||||||
|
|
||||||
|
// Kill the monitor thread if it exists
|
||||||
|
thread_info info;
|
||||||
|
if(get_thread_info(_monitor_thread,&info)==B_OK)
|
||||||
|
kill_thread(_monitor_thread);
|
||||||
|
|
||||||
|
cursormanager->RemoveAppCursors(_signature.String());
|
||||||
|
delete_sem(_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Starts the ServerApp monitoring for messages
|
||||||
|
\return false if the application couldn't start, true if everything went OK.
|
||||||
|
*/
|
||||||
|
bool ServerApp::Run(void)
|
||||||
|
{
|
||||||
|
// Unlike a BApplication, a ServerApp is *supposed* to return immediately
|
||||||
|
// when its Run() function is called.
|
||||||
|
_monitor_thread=spawn_thread(MonitorApp,_signature.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Pings the target app to make sure it's still working
|
||||||
|
\return true if target is still "alive" and false if "He's dead, Jim."
|
||||||
|
"But that's impossible..."
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
bool ServerApp::PingTarget(void)
|
||||||
|
{
|
||||||
|
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",_signature.String());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_applink->SetPort(serverport);
|
||||||
|
_applink->SetOpCode(DELETE_APP);
|
||||||
|
_applink->Attach(&_monitor_thread,sizeof(thread_id));
|
||||||
|
_applink->Flush();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief The thread function ServerApps use to monitor messages
|
||||||
|
\param data Pointer to the thread's ServerApp object
|
||||||
|
\return Throwaway value - always 0
|
||||||
|
*/
|
||||||
|
int32 ServerApp::MonitorApp(void *data)
|
||||||
|
{
|
||||||
|
ServerApp *app=(ServerApp *)data;
|
||||||
|
|
||||||
|
// Message-dispatching loop for the ServerApp
|
||||||
|
int32 msgcode;
|
||||||
|
int8 *msgbuffer=NULL;
|
||||||
|
ssize_t buffersize,bytesread;
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
buffersize=port_buffer_size(app->_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(app->_receiver,&msgcode,msgbuffer,buffersize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
bytesread=read_port(app->_receiver,&msgcode,NULL,0);
|
||||||
|
if (bytesread != B_BAD_PORT_ID && bytesread != B_TIMED_OUT && bytesread != B_WOULD_BLOCK)
|
||||||
|
{
|
||||||
|
switch(msgcode)
|
||||||
|
{
|
||||||
|
// -------------- 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.
|
||||||
|
write_port(app->_sender, msgcode, msgbuffer, buffersize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QUIT_APP:
|
||||||
|
{
|
||||||
|
// If we are using the real, accelerated version of the
|
||||||
|
// DisplayDriver, we do NOT want the user to be able shut down
|
||||||
|
// the server. The results would NOT be pretty
|
||||||
|
if(DISPLAYDRIVER==HWDRIVER)
|
||||||
|
{
|
||||||
|
// 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
|
||||||
|
app->_applink->SetOpCode(B_QUIT_REQUESTED);
|
||||||
|
app->_applink->Flush();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// -------------- 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->_signature.String());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
app->_applink->SetPort(serverport);
|
||||||
|
app->_applink->SetOpCode(DELETE_APP);
|
||||||
|
app->_applink->Attach(&app->_monitor_thread,sizeof(thread_id));
|
||||||
|
app->_applink->Flush();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
app->DispatchMessage(msgcode, msgbuffer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(buffersize>0)
|
||||||
|
delete msgbuffer;
|
||||||
|
|
||||||
|
if(msgcode==B_QUIT_REQUESTED)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_thread(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Handler function for BApplication API messages
|
||||||
|
\param code Identifier code for the message. Equivalent to BMessage::what
|
||||||
|
\param buffer Any attachments
|
||||||
|
|
||||||
|
Note that the buffer's exact format is determined by the particular message.
|
||||||
|
All attachments are placed in the buffer via a PortLink, so it will be a
|
||||||
|
matter of casting and incrementing an index variable to access them.
|
||||||
|
*/
|
||||||
|
void ServerApp::DispatchMessage(int32 code, int8 *buffer)
|
||||||
|
{
|
||||||
|
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:
|
||||||
|
{
|
||||||
|
// TODO: Uncomment when ServerWindow has been implemented
|
||||||
|
/*
|
||||||
|
// 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;
|
||||||
|
*/ break;
|
||||||
|
}
|
||||||
|
case DELETE_WINDOW:
|
||||||
|
{
|
||||||
|
// TODO: Uncomment when ServerWindow has been implemented
|
||||||
|
/*
|
||||||
|
// Received from a ServerWindow when its window quits
|
||||||
|
|
||||||
|
// Attached data:
|
||||||
|
// 1) thread_id ServerWindow ID
|
||||||
|
thread_id winid;
|
||||||
|
ServerWindow *w;
|
||||||
|
for(int32 i=0;i<_winlist->CountItems();i++)
|
||||||
|
{
|
||||||
|
w=(ServerWindow*)_winlist->ItemAt(i);
|
||||||
|
if(w->thread==winid)
|
||||||
|
{
|
||||||
|
_winlist->RemoveItem(w);
|
||||||
|
delete w;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/ break;
|
||||||
|
}
|
||||||
|
case GFX_SET_SCREEN_MODE:
|
||||||
|
{
|
||||||
|
// TODO: Enable when we have Desktop.h
|
||||||
|
/*
|
||||||
|
// 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));
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GFX_ACTIVATE_WORKSPACE:
|
||||||
|
{
|
||||||
|
// TODO: Enable when we have Desktop.h
|
||||||
|
/*
|
||||||
|
// Attached data
|
||||||
|
// 1) int32 workspace index
|
||||||
|
|
||||||
|
// Error-checking is done in ActivateWorkspace, so this is a safe call
|
||||||
|
ActivateWorkspace(*((int32*)index));
|
||||||
|
*/ break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Theoretically, we could just call the driver directly, but we will
|
||||||
|
// call the CursorManager's version to allow for future expansion
|
||||||
|
case SHOW_CURSOR:
|
||||||
|
{
|
||||||
|
cursormanager->ShowCursor();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HIDE_CURSOR:
|
||||||
|
{
|
||||||
|
cursormanager->HideCursor();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OBSCURE_CURSOR:
|
||||||
|
{
|
||||||
|
cursormanager->ObscureCursor();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SET_CURSOR_DATA:
|
||||||
|
{
|
||||||
|
// Attached data: 68 bytes of _appcursor data
|
||||||
|
|
||||||
|
// Get the data, update the app's _appcursor, and update the
|
||||||
|
// app's _appcursor if active.
|
||||||
|
int8 cdata[68];
|
||||||
|
memcpy(cdata, buffer, 68);
|
||||||
|
|
||||||
|
// Because we don't want an overaccumulation of these particular
|
||||||
|
// cursors, we will delete them if there is an existing one. It would
|
||||||
|
// otherwise be easy to crash the server by calling SetCursor a
|
||||||
|
// sufficient number of times
|
||||||
|
if(_appcursor)
|
||||||
|
cursormanager->DeleteCursor(_appcursor->_token);
|
||||||
|
|
||||||
|
_appcursor=new ServerCursor(cdata);
|
||||||
|
cursormanager->AddCursor(_appcursor);
|
||||||
|
cursormanager->SetCursor(_appcursor->_token);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SET_CURSOR_BCURSOR:
|
||||||
|
{
|
||||||
|
// TODO: Implement
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
printf("ServerApp %s received unhandled message code %lx\n",
|
||||||
|
_signature.String(),code);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
84
src/servers/app/server/ServerApp.h
Normal file
84
src/servers/app/server/ServerApp.h
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2001-2002, OpenBeOS
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
// File Name: ServerApp.h
|
||||||
|
// Author: DarkWyrm <bpmagic@columbus.rr.com>
|
||||||
|
// Description: Server-side BApplication counterpart
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
#ifndef _SERVERAPP_H_
|
||||||
|
#define _SERVERAPP_H_
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
#include <String.h>
|
||||||
|
class BMessage;
|
||||||
|
class PortLink;
|
||||||
|
class BList;
|
||||||
|
class DisplayDriver;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class ServerApp ServerApp.h
|
||||||
|
\brief Counterpart to BApplication within the app_server
|
||||||
|
*/
|
||||||
|
class ServerApp
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ServerApp(port_id sendport, port_id rcvport, char *signature);
|
||||||
|
~ServerApp(void);
|
||||||
|
|
||||||
|
bool Run(void);
|
||||||
|
static int32 MonitorApp(void *data);
|
||||||
|
void Lock(void);
|
||||||
|
void Unlock(void);
|
||||||
|
bool IsLocked(void);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Determines whether the application is the active one
|
||||||
|
\return true if active, false if not.
|
||||||
|
*/
|
||||||
|
bool IsActive(void) const { return _isactive; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Sets the ServerApp's active status
|
||||||
|
\param value The new status of the ServerApp.
|
||||||
|
|
||||||
|
Note that this function only changes a flag.
|
||||||
|
*/
|
||||||
|
void Activate(bool value) { _isactive=value; }
|
||||||
|
bool PingTarget(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void DispatchMessage(int32 code, int8 *buffer);
|
||||||
|
|
||||||
|
port_id _sender,_receiver;
|
||||||
|
BString _signature;
|
||||||
|
thread_id _monitor_thread;
|
||||||
|
team_id _target_id;
|
||||||
|
PortLink *_applink;
|
||||||
|
BList *_winlist, *_bmplist;
|
||||||
|
DisplayDriver *_driver;
|
||||||
|
ServerCursor *_appcursor;
|
||||||
|
sem_id _lock;
|
||||||
|
|
||||||
|
bool _isactive;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user