7cb02901 |
1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> |
2 | <HTML |
3 | ><HEAD |
4 | ><TITLE |
5 | >How to handle events and use the graphical trace reading service</TITLE |
6 | ><META |
7 | NAME="GENERATOR" |
8 | CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK |
9 | REL="HOME" |
10 | TITLE="Linux Trace Toolkit Viewer Developer Guide" |
11 | HREF="index.html"><LINK |
12 | REL="UP" |
13 | TITLE="Linux Trace Toolkit Viewer Graphical Module Tutorial" |
14 | HREF="c67.html"><LINK |
15 | REL="PREVIOUS" |
16 | TITLE="How to request background computation" |
17 | HREF="x81.html"></HEAD |
18 | ><BODY |
19 | CLASS="sect1" |
20 | BGCOLOR="#FFFFFF" |
21 | TEXT="#000000" |
22 | LINK="#0000FF" |
23 | VLINK="#840084" |
24 | ALINK="#0000FF" |
25 | ><DIV |
26 | CLASS="NAVHEADER" |
27 | ><TABLE |
28 | SUMMARY="Header navigation table" |
29 | WIDTH="100%" |
30 | BORDER="0" |
31 | CELLPADDING="0" |
32 | CELLSPACING="0" |
33 | ><TR |
34 | ><TH |
35 | COLSPAN="3" |
36 | ALIGN="center" |
37 | >Linux Trace Toolkit Viewer Developer Guide</TH |
38 | ></TR |
39 | ><TR |
40 | ><TD |
41 | WIDTH="10%" |
42 | ALIGN="left" |
43 | VALIGN="bottom" |
44 | ><A |
45 | HREF="x81.html" |
46 | ACCESSKEY="P" |
47 | >Prev</A |
48 | ></TD |
49 | ><TD |
50 | WIDTH="80%" |
51 | ALIGN="center" |
52 | VALIGN="bottom" |
53 | >Chapter 3. Linux Trace Toolkit Viewer Graphical Module Tutorial</TD |
54 | ><TD |
55 | WIDTH="10%" |
56 | ALIGN="right" |
57 | VALIGN="bottom" |
58 | > </TD |
59 | ></TR |
60 | ></TABLE |
61 | ><HR |
62 | ALIGN="LEFT" |
63 | WIDTH="100%"></DIV |
64 | ><DIV |
65 | CLASS="sect1" |
66 | ><H1 |
67 | CLASS="sect1" |
68 | ><A |
69 | NAME="AEN84" |
70 | >3.5. How to handle events and use the graphical trace reading service</A |
71 | ></H1 |
72 | ><P |
73 | > The events that are delivered by the main window are defined in |
74 | lttvwindow/lttvwindow.h. Let's describe them and their use in details. Remember |
75 | that you can refer to the control flow viewer module as an example. |
76 | </P |
77 | ><DIV |
78 | CLASS="sect2" |
79 | ><H2 |
80 | CLASS="sect2" |
81 | ><A |
82 | NAME="AEN87" |
83 | >3.5.1. Module Related API</A |
84 | ></H2 |
85 | ><P |
86 | > A viewer plugin is, before anything, a plugin. As a dynamically loadable |
87 | module, it thus has an init and a destroy function called whenever it is |
88 | loaded/initialized and unloaded/destroyed. A graphical module depends on |
89 | lttvwindow for construction of its viewer instances. In order to achieve |
90 | this, it must register its constructor function to the main window along |
91 | with button description or text menu entry description. A module keeps |
92 | a list of every viewer that currently sits in memory so it can destroy |
93 | them before the module gets unloaded/destroyed. |
94 | </P |
95 | ><P |
96 | > The contructor registration to the main windows adds button and menu |
97 | entry to each main window, thus allowing instanciation of viewers. |
98 | </P |
99 | ></DIV |
100 | ><DIV |
101 | CLASS="sect2" |
102 | ><H2 |
103 | CLASS="sect2" |
104 | ><A |
105 | NAME="AEN91" |
106 | >3.5.2. Main Window</A |
107 | ></H2 |
108 | ><P |
109 | > The main window is a container that offers menus, buttons and a |
110 | notebook. Some of those menus and buttons are part of the core of the |
111 | main window, others are dynamically added and removed when modules are |
112 | loaded/unloaded. |
113 | </P |
114 | ><P |
115 | > The notebook contains as much tabs as wanted. Each tab is linked with |
116 | a set of traces (traceset). Each trace contains many tracefiles (one |
117 | per cpu). A trace corresponds to a kernel being traced. A traceset |
118 | corresponds to many traces read together. The time span of a traceset |
119 | goes from the earliest start of all the traces to the latest end of all |
120 | the traces. |
121 | </P |
122 | ><P |
123 | > Inside each tab are added the viewers. When they interact with the main |
124 | window through the lttvwindow API, they affect the other viewers located |
125 | in the same tab as they are. |
126 | </P |
127 | ><P |
128 | > The insertion of many viewers in a tab permits a quick look at all the |
129 | information wanted in a glance. The main window does merge the read |
130 | requests from all the viewers in the same tab in a way that every viewer |
131 | will get exactly the events it asked for, while the event reading loop |
132 | and state update are shared. It improves performance of events delivery |
133 | to the viewers. |
134 | </P |
135 | ></DIV |
136 | ><DIV |
137 | CLASS="sect2" |
138 | ><H2 |
139 | CLASS="sect2" |
140 | ><A |
141 | NAME="AEN97" |
142 | >3.5.3. Viewer Instance Related API</A |
143 | ></H2 |
144 | ><P |
145 | > The lifetime of a viewer is as follows. The viewer constructor function |
146 | is called each time an instance view is created (one subwindow of this |
147 | viewer type is created by the user either by clicking on the menu item |
148 | or the button corresponding to the viewer). Thereafter, the viewer gets |
149 | hooks called for different purposes by the window containing it. These |
150 | hooks are detailed below. It also has to deal with GTK Events. Finally, |
151 | it can be destructed by having its top level widget unreferenced by the |
152 | main window or by any GTK Event causing a "destroy-event" signal on the |
153 | its top widget. Another possible way for it do be destroyed is if the |
154 | module gets unloaded. The module unload function will have to emit a |
155 | "destroy" signal on each top level widget of all instances of its viewers. |
156 | </P |
157 | ></DIV |
158 | ><DIV |
159 | CLASS="sect2" |
160 | ><H2 |
161 | CLASS="sect2" |
162 | ><A |
163 | NAME="AEN100" |
164 | >3.5.4. Notices from Main Window</A |
165 | ></H2 |
166 | ><P |
167 | ></P |
168 | ><DIV |
169 | CLASS="variablelist" |
170 | ><DL |
171 | ><DT |
172 | >time_window</DT |
173 | ><DD |
174 | ><P |
175 | >This is the time interval visible on the viewer's tab. Every |
176 | viewer that cares about being synchronised by respect to the |
177 | time with other viewers should register to this notification. |
178 | They should redraw all or part of their display when this |
179 | occurs.</P |
180 | ></DD |
181 | ><DT |
182 | >traceset</DT |
183 | ><DD |
184 | ><P |
185 | >This notification is called whenever a trace is added/removed |
186 | from the traceset. As it affects all the data displayed by the |
187 | viewer, it sould redraw itself totally.</P |
188 | ></DD |
189 | ><DT |
190 | >filter</DT |
191 | ><DD |
192 | ><P |
193 | >This feature has not been implemented yet.</P |
194 | ></DD |
195 | ><DT |
196 | >current_time</DT |
197 | ><DD |
198 | ><P |
199 | >Being able to zoom nearer a specific time or highlight a specific |
200 | time on every viewer in synchronicity implies that the viewer |
201 | has to shown a visual sign over the drawing or select an event |
202 | when it receives this notice. It should also inform the main |
203 | window with the appropriate report API function when a user |
204 | selects a specific time as being the current time.</P |
205 | ></DD |
206 | ><DT |
207 | >dividor</DT |
208 | ><DD |
209 | ><P |
210 | >This notice links the positions of the horizontal dividors |
211 | between the graphic display zone of every viewer and their Y axis, |
212 | typically showing processes, cpus, ...</P |
213 | ></DD |
214 | ></DL |
215 | ></DIV |
216 | ></DIV |
217 | ><DIV |
218 | CLASS="sect2" |
219 | ><H2 |
220 | CLASS="sect2" |
221 | ><A |
222 | NAME="AEN123" |
223 | >3.5.5. Reporting Changes to the Main Window</A |
224 | ></H2 |
225 | ><P |
226 | > In most cases, the enclosing window knows about updates such as described |
227 | in the Notification section higher. There are a few cases, however, where |
228 | updates are caused by actions known by a view instance. For example, |
229 | clicking in a view may update the current time; all viewers within |
230 | the same window must be told about the new current time to change the |
231 | currently highlighted time point. A viewer reports such events by calling |
232 | lttvwindow_report_current_time on its lttvwindow. The lttvwindow will |
233 | consequently call current_time_notify for each of its contained viewers. |
234 | </P |
235 | ><P |
236 | > Available report methods are : |
237 | <P |
238 | ></P |
239 | ><UL |
240 | ><LI |
241 | ><P |
242 | > lttvwindow_report_time_window : reports the new time window. |
243 | </P |
244 | ></LI |
245 | ><LI |
246 | ><P |
247 | > lttvwindow_report_current_time : reports the new current time. |
248 | </P |
249 | ></LI |
250 | ><LI |
251 | ><P |
252 | > lttvwindow_report_dividor : reports the new horizontal dividor's position. |
253 | </P |
254 | ></LI |
255 | ></UL |
256 | > |
257 | </P |
258 | ></DIV |
259 | ><DIV |
260 | CLASS="sect2" |
261 | ><H2 |
262 | CLASS="sect2" |
263 | ><A |
264 | NAME="AEN134" |
265 | >3.5.6. Requesting Events to Main Window</A |
266 | ></H2 |
267 | ><P |
268 | > Events can be requested by passing a EventsRequest structure to the main |
269 | window. They will be delivered later when the next g_idle functions |
270 | will be called. Event delivery is done by calling the event hook for |
271 | this event ID, or the main event hooks. A pointer to the EventsRequest |
272 | structure is passed as hook_data to the event hooks of the viewers. |
273 | </P |
274 | ><P |
275 | > EventsRequest consists in |
276 | <P |
277 | ></P |
278 | ><UL |
279 | ><LI |
280 | ><P |
281 | > a pointer to the viewer specific data structure |
282 | </P |
283 | ></LI |
284 | ><LI |
285 | ><P |
286 | > a start timestamp or position |
287 | </P |
288 | ></LI |
289 | ><LI |
290 | ><P |
291 | > a stop_flag, ending the read process when set to TRUE |
292 | </P |
293 | ></LI |
294 | ><LI |
295 | ><P |
296 | > a end timestamp and/or position and/or number of events to read |
297 | </P |
298 | ></LI |
299 | ><LI |
300 | ><P |
301 | > hook lists to call for traceset/trace/tracefile begin and end, and for each |
302 | event (event hooks and event_by_id hooks). |
303 | </P |
304 | ></LI |
305 | ></UL |
306 | > |
307 | </P |
308 | ><P |
309 | > The main window will deliver events for every EventRequests it has |
310 | pending through an algorithm that guarantee that all events requested, |
311 | and only them, will be delivered to the viewer between the call of the |
312 | tracefile_begin hooks and the call of the tracefile_end hooks. |
313 | </P |
314 | ><P |
315 | > If a viewer wants to stop the event request at a certain point inside the |
316 | event hooks, it has to set the stop_flag to TRUE and return TRUE from the |
317 | hook function. Then return value will stop the process traceset. Then, |
318 | the main window will look for the stop_flag and remove the EventRequests |
319 | from its lists, calling the process_traceset_end for this request (it |
320 | removes hooks from the context and calls the after hooks). |
321 | </P |
322 | ><P |
323 | > It no stop_flag is risen, the end timestamp, end position or number |
324 | of events to read has to be reached to determine the end of the |
325 | request. Otherwise, the end of traceset does determine it. |
326 | </P |
327 | ></DIV |
328 | ><DIV |
329 | CLASS="sect2" |
330 | ><H2 |
331 | CLASS="sect2" |
332 | ><A |
333 | NAME="AEN152" |
334 | >3.5.7. GTK Events</A |
335 | ></H2 |
336 | ><DIV |
337 | CLASS="sect3" |
338 | ><H3 |
339 | CLASS="sect3" |
340 | ><A |
341 | NAME="AEN154" |
342 | >3.5.7.1. Events and Signals</A |
343 | ></H3 |
344 | ><P |
345 | > GTK is quite different from the other graphical toolkits around |
346 | there. The main difference resides in that there are many X Windows |
347 | inside one GtkWindow, instead of just one. That means that X events are |
348 | delivered by the glib main loop directly to the widget corresponding to |
349 | the GdkWindow affected by the X event. |
350 | </P |
351 | ><P |
352 | > Event delivery to a widget emits a signal on that widget. Then, if a |
353 | handler is connected to this widget's signal, it will be executed. There |
354 | are default handlers for signals, connected at class instantiation |
355 | time. There is also the possibility to connect other handlers to these |
356 | signals, which is what should be done in most cases when a viewer needs |
357 | to interact with X in any way. |
358 | </P |
359 | ><P |
360 | > Signal emission and propagation is described there : |
361 | |
362 | <P |
363 | ></P |
364 | ><UL |
365 | ><LI |
366 | ><P |
367 | > http://www.gtk.org/tutorial/sec-signalemissionandpropagation.html |
368 | </P |
369 | ></LI |
370 | ></UL |
371 | > |
372 | </P |
373 | ><P |
374 | > For further information on the GTK main loop (now a wrapper over glib main loop) |
375 | see : |
376 | |
377 | <P |
378 | ></P |
379 | ><UL |
380 | ><LI |
381 | ><P |
382 | > http://developer.gnome.org/doc/API/2.0/gtk/gtk-General.html |
383 | </P |
384 | ></LI |
385 | ><LI |
386 | ><P |
387 | > http://developer.gnome.org/doc/API/2.0/glib/glib-The-Main-Event-Loop.html |
388 | </P |
389 | ></LI |
390 | ></UL |
391 | > |
392 | </P |
393 | ><P |
394 | > For documentation on event handling in GTK/GDK, see : |
395 | |
396 | <P |
397 | ></P |
398 | ><UL |
399 | ><LI |
400 | ><P |
401 | > http://developer.gnome.org/doc/API/2.0/gdk/gdk-Events.html |
402 | </P |
403 | ></LI |
404 | ><LI |
405 | ><P |
406 | > http://developer.gnome.org/doc/API/2.0/gdk/gdk-Event-Structures.html |
407 | </P |
408 | ></LI |
409 | ></UL |
410 | > |
411 | </P |
412 | ><P |
413 | > Signals can be connected to handlers, emitted, propagated, blocked, |
414 | stopped. See : |
415 | |
416 | <P |
417 | ></P |
418 | ><UL |
419 | ><LI |
420 | ><P |
421 | > http://developer.gnome.org/doc/API/2.0/gobject/gobject-Signals.html |
422 | </P |
423 | ></LI |
424 | ></UL |
425 | > |
426 | </P |
427 | ></DIV |
428 | ><DIV |
429 | CLASS="sect3" |
430 | ><H3 |
431 | CLASS="sect3" |
432 | ><A |
433 | NAME="AEN178" |
434 | >3.5.7.2. The "expose_event"</A |
435 | ></H3 |
436 | ><P |
437 | > Provides the exposed region in the GdkEventExpose structure. |
438 | </P |
439 | ><P |
440 | > There are two ways of dealing with exposures. The first one is to directly |
441 | draw on the screen and the second one is to draw in a pixmap buffer, |
442 | and then to update the screen when necessary. |
443 | </P |
444 | ><P |
445 | > In the first case, the expose event will be responsible for registering |
446 | hooks to process_traceset and require time intervals to the main |
447 | window. So, in this scenario, if a part of the screen is damaged, the |
448 | trace has to be read to redraw the screen. |
449 | </P |
450 | ><P |
451 | > In the second case, with a pixmap buffer, the expose handler is only |
452 | responsible of showing the pixmap buffer on the screen. If the pixmap |
453 | buffer has never been filled with a drawing, the expose handler may ask |
454 | for it to be filled. |
455 | </P |
456 | ><P |
457 | > The interest of using events request to the main window instead of reading |
458 | the events directly from the trace comes from the fact that the main |
459 | window does merge requests from the different viewers in the same tab so |
460 | that the read loop and the state update is shared. As viewers will, in |
461 | the common scenario, request the same events, only one pass through the |
462 | trace that will call the right hooks for the right intervals will be done. |
463 | </P |
464 | ><P |
465 | > When the traceset read is over for a events request, the traceset_end |
466 | hook is called. It has the responsibility of finishing the drawing if |
467 | some parts still need to be drawn and to show it on the screen (if the |
468 | viewer uses a pixmap buffer). |
469 | </P |
470 | ><P |
471 | > It can add dotted lines and such visual effects to enhance the user's |
472 | experience. |
473 | </P |
474 | ></DIV |
475 | ></DIV |
476 | ></DIV |
477 | ><DIV |
478 | CLASS="NAVFOOTER" |
479 | ><HR |
480 | ALIGN="LEFT" |
481 | WIDTH="100%"><TABLE |
482 | SUMMARY="Footer navigation table" |
483 | WIDTH="100%" |
484 | BORDER="0" |
485 | CELLPADDING="0" |
486 | CELLSPACING="0" |
487 | ><TR |
488 | ><TD |
489 | WIDTH="33%" |
490 | ALIGN="left" |
491 | VALIGN="top" |
492 | ><A |
493 | HREF="x81.html" |
494 | ACCESSKEY="P" |
495 | >Prev</A |
496 | ></TD |
497 | ><TD |
498 | WIDTH="34%" |
499 | ALIGN="center" |
500 | VALIGN="top" |
501 | ><A |
502 | HREF="index.html" |
503 | ACCESSKEY="H" |
504 | >Home</A |
505 | ></TD |
506 | ><TD |
507 | WIDTH="33%" |
508 | ALIGN="right" |
509 | VALIGN="top" |
510 | > </TD |
511 | ></TR |
512 | ><TR |
513 | ><TD |
514 | WIDTH="33%" |
515 | ALIGN="left" |
516 | VALIGN="top" |
517 | >How to request background computation</TD |
518 | ><TD |
519 | WIDTH="34%" |
520 | ALIGN="center" |
521 | VALIGN="top" |
522 | ><A |
523 | HREF="c67.html" |
524 | ACCESSKEY="U" |
525 | >Up</A |
526 | ></TD |
527 | ><TD |
528 | WIDTH="33%" |
529 | ALIGN="right" |
530 | VALIGN="top" |
531 | > </TD |
532 | ></TR |
533 | ></TABLE |
534 | ></DIV |
535 | ></BODY |
536 | ></HTML |
537 | > |