Changes between Initial Version and Version 1 of doc-devel/events


Ignore:
Timestamp:
06/21/11 11:25:02 (13 years ago)
Author:
slavazanko
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • doc-devel/events

    v1 v1  
     1= Event system = 
     2 
     3The subsystem of events used in mc is based on fast binary trees engine. 
     4 
     5== Introduction == 
     6 
     7Subsystem of events is primarily designed to detach event source and event handler in source code level. For example, VFS module uses function to show 
     8messages, which is defined in the source code (not in the lib). In the lib, definition of this function will be difficult (because the function does 
     9a lot of calls of other functions from src). In this case, the transform of this function to event handler is needed, and the display messages process 
     10can be used as an event. Function as event handler should be registered at early stage of mc start. Later just call the event, absolutely without 
     11worrying whether the handler is tied to the event, and which function is an event handler now (in some situation, plugin will load and reassign this event handler to itself). 
     12 
     13 
     14=== Usage === 
     15 
     16Events are applicable in any case. Sometimes it is hard to decide whether it should be a common function or it should be an event handler. The replacement of all functions used in keybindings process to event handler is good choice (or parts of the 'switch () {case:}' in keybindings handlers). All keybindings are described in lib/keybind.h. 
     17 
     18The second argument to choose the solution (event handler or function) should be thought whether that transformation of function to the event handler is easy, the inverse process (handler to function) would be more difficult because one event can have multiple handlers and each handler may depend to another. 
     19 
     20A third argument in the choice in favor of the event handlers can be a plug-ins (in future). In this case events is a way to give access to internal application resources without providing a low-level API. All plug-ins need is to know what and how call the event with proper structure type (#include "lib/event.h"). 
     21 
     22 
     23== Structure == 
     24 
     25In general, the subsystem of events can be represented as following: 
     26{{{ 
     27   ------------------------------------            } 
     28   |Group1        Group2   ...   GroupN|            }   Event groups (GTree) 
     29   -------------------------------------           } 
     30       |             |             | 
     31      /|\           /|\           /|\ 
     32     / | \         / | ...       ... eventN        } 
     33    /  |  \       /  ...                            } 
     34   /   |   \      ...                                } Events by groups 
     35   |   |    event3                                   } (GTree for any group) 
     36   |   event2                                       } 
     37   event1                                          } 
     38   | | |  | 
     39   f1f2...fN                                       } list of event handlers (GPtrArray for any event) 
     40}}} 
     41 
     42This scheme allows to group events, and perform several handlers for one event. 
     43 
     44== Requirements for event handlers == 
     45 
     46The following function prototype is event handler: 
     47{{{ 
     48gboolean mc_event_callback_func_t ( 
     49    const gchar *event_group, 
     50    const gchar *event_name, 
     51    gpointer init_data, 
     52    gpointer event_data 
     53); 
     54}}} 
     55 
     56where: 
     57 event_group:: 
     58  name of the group, where event was initiated 
     59 event_name:: 
     60   event name. event_name ans event_group uniquely identify an event. These parameters can be useful if event handler is tied to several events and the distinguish between different events (for example, function of logging) is required. 
     61 init_data:: 
     62    Arbitrary data, provided to the event handler. This data is provided by adding a handler to the event (the initialization data). 
     63 event_data:: 
     64    Data provided to the handler when the event occurred. 
     65 
     66Handler should return TRUE to allow running all other handlers tied to this event; or FALSE if it is necessary to stop further processing of event (the remaining handlers are not called). 
     67 
     68If one event will have multiple handlers, the order of execution is "Last added - first executed". This allows to override the standard event handlers (eg, in plug-ins). 
     69 
     70=== Passing parameters to event handlers. Returning rezults === 
     71 
     72Due to the unification of the event handlers, there is no possibility to pass a certain number of parameters and get the results of execution. Pass of a single parameter (or get one result of an event handler) can be made as simple type casting for one variable when event is called. But this way isn't applicable if pass of several parameters (or get multiple return values) is required. 
     73 
     74To solve this problem, you can pass the previously defined structure as universal pointer event_data. All structures used in the event handlers should be defined in the lib/event-types.h. 
     75 
     76This way (the pass parameters as pointer to structure) has advantages and disadvantages. 
     77 
     78Advantages: 
     79 * any number of parameters and their types; 
     80 * any number of return values and their types. 
     81 
     82Disadvantages: 
     83 * probability of error: call the event with the wrong structure. In this case,    the handler will cast pointer to the structure on which it was designed. At this point funny bugs and very long debugging process (especially if segfault doesn't occur immediately) are possible; 
     84 * in order for an event handler and the initiator of the event to "communicate" with each other, previously defined structures is needed. 
     85 
     86 
     87== Examples == 
     88 
     89=== Logging === 
     90 
     91Consider the example of a temporary handler which simply logged the order of certain events (for example, to detect infinite loop). 
     92 
     93Here event handler: 
     94{{{ 
     95gboolean 
     96mc_temp_event_logger (const gchar *event_group, const gchar *event_name, 
     97                      gpointer init_data, gpointer data) 
     98{ 
     99    (void) init_data; 
     100    (void) data; 
     101 
     102    mc_log("Event: %s:%s",event_group,event_name); 
     103    return TRUE; 
     104} 
     105}}} 
     106 
     107Add the following lines into src/event_init.c before "{NULL, NULL, NULL, NULL}" line as one record to the initialization structure. 
     108 
     109{{{ 
     110{MCEVENT_GROUP_CORE, "clipboard_file_to_ext_clip", mc_temp_event_logger, NULL}, 
     111{MCEVENT_GROUP_CORE, "clipboard_file_from_ext_clip", mc_temp_event_logger, NULL}, 
     112{MCEVENT_GROUP_CORE, "clipboard_text_to_file", mc_temp_event_logger, NULL}, 
     113{MCEVENT_GROUP_CORE, "clipboard_text_from_file", mc_temp_event_logger, NULL}, 
     114 
     115...(there any other events which you want to monitor)... 
     116}}}