AppServer class###############The AppServer class sits at the top of the hierarchy, starting andstopping services, monitoring for messages, and so forth.Member Functions================- AppServer(void)- ~AppServer(void)- static int32 Poller(void \*data)- static int32 Picasso(void \*data)- thread_id Run(void)- void MainLoop(void)- bool LoadDecorator(const char\*path)- void DispatchMessage(int32 code,int8 \*buffer)- void Broadcast(int32 code)- void HandleKeyMessage(int32 code, int8 \*buffer)Global Functions================Decorator \* instantiate_decorator(Layer \*owner, uint32 wflags, uint32 wlook)AppServer(void)===============1. Create the message and input ports2. Create any necessary semaphores for regulating the 3 main threads3. Initialize all member variables4. Allocate the application BList5. Read in and process all configuration data6. Initialize the desktop7. Spawn the Picasso and Poller threads~AppServer(void)================1. Shut down the desktop2. Empty and delete the application list3. Wait for Picasso and Poller to exit4. Free any allocated heap spacevoid MainLoop(void)===================MainLoop is one large loop used to monitor the main message port inthe app_server thread. This is a standard port-monitoring loop code:1. Call port_buffer_size - which will block if the port is empty2. Allocate a buffer on the heap if the port buffer size is greater than 03. Read the port4. Pass specified messages to DispatchMessage() for processing, spittingout an error message to stderr if the message's code is unrecognized5. Return from DispatchMessage() and free the message buffer if one wasallocated6. If the message code matches the B_QUIT_REQUESTED definition and thequit_server flag is true, fall out of the infinite message-monitoringloopvoid DispatchMessage(int32 code, int8 \*buffer)===============================================DispatchMessage implements all the code necessary to respond to agiven message sent to the app_server on its main port. This allows forclearer and more manageable code.CREATE_APP----------Sent by a new BApplication object via synchronous PortLink messaging.Set up the corresponding ServerApp and reply to the BApplication withthe new port to which it will send future communications with the AppServer.Attached Data:+-----------------------------------+-----------------------------------+| port_id reply_port | port to which the server is to || | reply in response to the current || | message |+-----------------------------------+-----------------------------------+| port_id app_port | message port for the requesting || | BApplication |+-----------------------------------+-----------------------------------+| int16 sig_length | length of the following || | application signature |+-----------------------------------+-----------------------------------+| const char \*signature | Signature of the requesting || | BApplication |+-----------------------------------+-----------------------------------+1. Get all attached data2. Acquire the application list lock3. Allocate a ServerApp object and add it to the list4. Release application list lock5. Acquire active application pointer lock6. Update active application pointer7. Release active application lock8. Send the message SET_SERVER_PORT (with the ServerApp's receiver portattached) to the reply port9. Run() the new ServerApp instanceDELETE_APP----------Sent by a ServerApp when told to quit either by its BApplication orthe Server itself (during shutdown). It is identified by the unique IDassigned to its thread.Attached Data:+-----------------------------------+-----------------------------------+| thread_id app_thread | Thread id of the ServerApp || | sending this message |+-----------------------------------+-----------------------------------+1. Get app's thread_id2. Acquire application list lock3. Iterate through the application list, searching for the ServerAppobject with the sent thread_id4. Remove the object from the list and delete it5. Acquire active application lock6. Check to see if the application is active7. If application is/was active, set it to the previous application inthe list or NULL if there are no other active applications8. Release application list lock9. Release active application lockGET_SCREEN_MODE---------------Received from the Haiku Input Server when requesting the currentscreen settings via synchronous PortLink messaging. This is atemporary solution which will be deprecated as soon as the BScreenclass is complete.Attached Data:+-----------------------------------+-----------------------------------+| port_id reply_port | port to which the server is to || | reply in response to the current || | message |+-----------------------------------+-----------------------------------+1. Get height, width, and color depth from the global graphics driverobject2. Attach via PortLink and reply to senderB_QUIT_REQUESTED----------------Encountered only under testing situations where the Server is told toquit.Attached Data: None1. Set quit_server flag to true2. Call Broadcast(QUIT_APP)SET_DECORATOR-------------Received from just about anything when a new window decorator ischosenAttached Data:+-----------------------------------+-----------------------------------+| const char \*path | Path to the proposed new || | decorator |+-----------------------------------+-----------------------------------+1. Get the path from the buffer2. Call LoadDecorator()void Run(void)==============Run() exists mostly for consistency with other regular applications.1) Call MainLoop()bool LoadDecorator(const char \*path)=====================================Allows for a simple way to change the current window decoratorsystemwide simply by specifying the path to the desired Decoratoraddon.1. Load the passed string as the path to an addon.2. Load all necessary symbols for the decorator3. Return false if things didn't go so well4. Call Broadcast(UPDATE_DECORATOR)5. Return truestatic int32 Picasso(void \*data)=================================Picasso is a function, despite its name, dedicated to ensuring thatthe server deallocates resources to a dead application. It consists ofa while(!quit_server) loop as follows:1) Acquire the appliction list lock2) Iterate through the list, calling each ServerApp object'sPingTarget() method.3) If PingTarget returns false, remove the ServerApp from the list anddelete it.4) Release the appliction list lock5) snooze for 3 secondsstatic int32 Poller(void \*data)================================Poller is the main workhorse of the AppServer class, polling theServer's input port constantly for any messages from the Input Serverand calling the appropriate handlers. Like Picasso, it, too, is mostlya while(!quit_server) loop.1. Call port_buffer_size_etc() with a timeout of 3 seconds.2. Check to see if the port_buffer_size_etc() timed out and do acontinue to next iteration if it did.3. Allocate a buffer on the heap if the port buffer size is greater than 04. Read the port5. Pass specified messages to DispatchMessage() for processing, spittingout an error message to stderr if the message's code is unrecognized6. Return from DispatchMessage() and free the message buffer if one wasallocatedDecorator \* instantiate_decorator(Layer \*owner, uint32 wflags, uint32 wlook)==============================================================================instantiate_decorator returns a new instance of the decoratorcurrently in use. The caller is responsible for the memory allocatedfor the returned object.1. Acquire the decorator lock2. If create_decorator is NULL, create a new instance of the defaultdecorator3. If create_decorator is non-NULL, create a new decorator instance bycalling AppServer::create_decorator().4. Release the decorator lock5. Return the newly allocated instancevoid Broadcast(int32 code)==========================Broadcast() provides the AppServer class with an easy way to send aquick message to all ServerApps. Primarily, this is called when a fontor decorator has changed, or when the server is shutting down. It isnot intended to do anything except send a quick message which requiresno extra data, such as for some upadate signalling.1. Acquire application list lock2. Create a PortLink instance and set its message code to the passedparameter.3. Iterate through the application list, targeting the PortLink instanceto each ServerApp's message port and calling Flush().4. Release application list lockvoid HandleKeyMessage(int32 code, int8 \*buffer)================================================Called from DispatchMessage to filter out App Server events andotherwise send keystrokes to the active application.B_KEY_DOWN----------Sent when the user presses (or holds down) a key that's been mapped toa character.Attached Data:+-----------------------------------+-----------------------------------+| int64 when | event time in seconds since || | 1/1/70 |+-----------------------------------+-----------------------------------+| int32 rawcode | code for the physical key pressed |+-----------------------------------+-----------------------------------+| int32 repeat_count | number of times a key has been || | repeated |+-----------------------------------+-----------------------------------+| int32 modifiers | flags signifying the states of || | the modifier keys |+-----------------------------------+-----------------------------------+| int32 state_count | number of bytes to follow || | containing the state of all keys |+-----------------------------------+-----------------------------------+| int8 \*states | array of the state of all keys at || | the time of the event |+-----------------------------------+-----------------------------------+| int8 utf8data[3] | UTF-8 data generated |+-----------------------------------+-----------------------------------+| int8 charcount | number of bytes to follow || | containing the string generated || | (usually 1) |+-----------------------------------+-----------------------------------+| const char \*string | null-terminated string generated || | by the keystroke |+-----------------------------------+-----------------------------------+| int32 raw_char | modifier-independent ASCII code || | for the character |+-----------------------------------+-----------------------------------+1. Get all attached data2. If the command modifier is down, check for Left Ctrl+Left Alt+LeftShift+F12 and reset the workspace to 640 x 480 x 256 @ 60Hz and returnif true3. If the command modifier is down, check for Alt+F1 through Alt+F12 andset workspace and return if true4. If the control modifier is true, check for B_CONTROL_KEY+Tab and, iftrue, find and send to the Deskbar.5. Acquire the active application lock6. Create a PortLink instance, target the active ServerApp's senderport, set the opcode to B_KEY_DOWN, attach the buffer en masse, and sendit to the BApplication.7. Release the active application lockB_KEY_UP--------Sent when the user releases a key that's been mapped to a character.Attached Data:+-----------------------------------+-----------------------------------+| int64 when | event time in seconds since || | 1/1/70 |+-----------------------------------+-----------------------------------+| int32 rawcode | code for the physical key pressed |+-----------------------------------+-----------------------------------+| int32 modifiers | flags signifying the states of || | the modifier keys |+-----------------------------------+-----------------------------------+| int32 state_count | number of bytes to follow || | containing the state of all keys |+-----------------------------------+-----------------------------------+| int8 \*states | array of the state of all keys at || | the time of the event |+-----------------------------------+-----------------------------------+| int8 utf8data[3] | UTF-8 data generated |+-----------------------------------+-----------------------------------+| int8 charcount | number of bytes to follow || | containing the string generated || | (usually 1) |+-----------------------------------+-----------------------------------+| const char \*string | null-terminated string generated || | by the keystroke |+-----------------------------------+-----------------------------------+| int32 raw_char | modifier-independent ASCII code || | for the character |+-----------------------------------+-----------------------------------+1. Get all attached data2. Acquire the active application lock3. Create a PortLink instance, target the active ServerApp's senderport, set the opcode to B_KEY_UP, attach the buffer en masse, and sendit to the BApplication.4. Release the active application lockB_UNMAPPED_KEY_DOWN-------------------Sent when the user presses a key that has not been mapped to acharacter.Attached Data:+-----------------------------------+-----------------------------------+| int64 when | event time in seconds since || | 1/1/70 |+-----------------------------------+-----------------------------------+| int32 rawcode | code for the physical key pressed |+-----------------------------------+-----------------------------------+| int32 modifiers | flags signifying the states of || | the modifier keys |+-----------------------------------+-----------------------------------+| int8 state_count | number of bytes to follow || | containing the state of all keys |+-----------------------------------+-----------------------------------+| int8 \*states | array of the state of all keys at || | the time of the event |+-----------------------------------+-----------------------------------+1. Acquire the active application lock2. Create a PortLink instance, target the active ServerApp's senderport, set the opcode to B_UNMAPPED_KEY_DOWN, attach the buffer en masse,and send it to the BApplication.3. Release the active application lockB_UNMAPPED_KEY_UP-----------------Sent when the user presses a key that has not been mapped to acharacter.Attached Data:+-----------------------------------+-----------------------------------+| int64 when | event time in seconds since || | 1/1/70 |+-----------------------------------+-----------------------------------+| int32 rawcode | code for the physical key pressed |+-----------------------------------+-----------------------------------+| int32 modifiers | flags signifying the states of || | the modifier keys |+-----------------------------------+-----------------------------------+| int8 state_count | number of bytes to follow || | containing the state of all keys |+-----------------------------------+-----------------------------------+| int8 \*states | array of the state of all keys at || | the time of the event |+-----------------------------------+-----------------------------------+1. Acquire the active application lock2. Create a PortLink instance, target the active ServerApp's senderport, set the opcode to B_UNMAPPED_KEY_UP, attach the buffer en masse,and send it to the BApplication.3. Release the active application lockB_MODIFIERS_CHANGED-------------------Sent when the user presses or releases one of the modifier keysAttached Data:+-----------------------------------+-----------------------------------+| int64 when | event time in seconds since || | 1/1/70 |+-----------------------------------+-----------------------------------+| int32 modifiers | flags signifying the states of || | the modifier keys |+-----------------------------------+-----------------------------------+| int32 old_modifiers | former states of the modifier || | keys |+-----------------------------------+-----------------------------------+| int8 state_count | number of bytes to follow || | containing the state of all keys |+-----------------------------------+-----------------------------------+| int8 \*states | array of the state of all keys at || | the time of the event |+-----------------------------------+-----------------------------------+1. Acquire the active application lock2. Create a PortLink instance, target the active ServerApp's senderport, set the opcode to B_MODIFIERS_CHANGED, attach the buffer en masse,and send it to the BApplication.3. Release the active application lock