unref tooltip when close tab
[lttv.git] / ltt / branches / poly / lttv / modules / gui / controlflow / eventhooks.c
... / ...
CommitLineData
1/* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Mathieu Desnoyers
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
19
20/*****************************************************************************
21 * Hooks to be called by the main window *
22 *****************************************************************************/
23
24
25/* Event hooks are the drawing hooks called during traceset read. They draw the
26 * icons, text, lines and background color corresponding to the events read.
27 *
28 * Two hooks are used for drawing : draw_before and draw_after hooks. The
29 * draw_before is called before the state update that occurs with an event and
30 * the draw_after hook is called after this state update.
31 *
32 * The draw_before hooks fulfill the task of drawing the visible objects that
33 * corresponds to the data accumulated by the draw_after hook.
34 *
35 * The draw_after hook accumulates the data that need to be shown on the screen
36 * (items) into a queue. Then, the next draw_before hook will draw what that
37 * queue contains. That's the Right Way (TM) of drawing items on the screen,
38 * because we need to draw the background first (and then add icons, text, ...
39 * over it), but we only know the length of a background region once the state
40 * corresponding to it is over, which happens to be at the next draw_before
41 * hook.
42 *
43 * We also have a hook called at the end of a chunk to draw the information left
44 * undrawn in each process queue. We use the current time as end of
45 * line/background.
46 */
47
48
49//#define PANGO_ENABLE_BACKEND
50#include <gtk/gtk.h>
51#include <gdk/gdk.h>
52#include <glib.h>
53#include <assert.h>
54#include <string.h>
55#include <stdio.h>
56
57//#include <pango/pango.h>
58
59#include <ltt/event.h>
60#include <ltt/time.h>
61#include <ltt/type.h>
62
63#include <lttv/lttv.h>
64#include <lttv/hook.h>
65#include <lttv/state.h>
66#include <lttvwindow/lttvwindow.h>
67#include <lttvwindow/lttvwindowtraces.h>
68
69
70#include "eventhooks.h"
71#include "cfv.h"
72#include "processlist.h"
73#include "drawing.h"
74#include "cfv-private.h"
75
76
77#define MAX_PATH_LEN 256
78
79
80#if 0
81typedef struct _ProcessAddClosure {
82 ControlFlowData *cfd;
83 guint trace_num;
84} ProcessAddClosure;
85
86static void process_add(gpointer key,
87 gpointer value,
88 gpointer user_data)
89{
90 LttvProcessState *process = (LttvProcessState*)value;
91 ProcessAddClosure *closure = (ProcessAddClosure*)user_data;
92 ControlFlowData *control_flow_data = closure->cfd;
93 guint trace_num = closure->trace_num;
94
95 /* Add process to process list (if not present) */
96 guint pid;
97 LttTime birth;
98 guint y = 0, height = 0, pl_height = 0;
99
100 ProcessList *process_list =
101 guicontrolflow_get_process_list(control_flow_data);
102
103 pid = process->pid;
104 birth = process->creation_time;
105 const gchar *name = g_quark_to_string(process->name);
106 HashedProcessData *hashed_process_data = NULL;
107
108 if(processlist_get_process_pixels(process_list,
109 pid,
110 &birth,
111 trace_num,
112 &y,
113 &height,
114 &hashed_process_data) == 1)
115 {
116 /* Process not present */
117 processlist_add(process_list,
118 pid,
119 &birth,
120 trace_num,
121 name,
122 &pl_height,
123 &hashed_process_data);
124 processlist_get_process_pixels(process_list,
125 pid,
126 &birth,
127 trace_num,
128 &y,
129 &height,
130 &hashed_process_data);
131 drawing_insert_square( control_flow_data->drawing, y, height);
132 }
133}
134#endif //0
135
136
137/* Action to do when background computation completed.
138 *
139 * Wait for all the awaited computations to be over.
140 */
141
142gint background_ready(void *hook_data, void *call_data)
143{
144 ControlFlowData *control_flow_data = (ControlFlowData *)hook_data;
145 LttvTrace *trace = (LttvTrace*)call_data;
146 LttvTracesetContext *tsc =
147 lttvwindow_get_traceset_context(control_flow_data->tab);
148
149 control_flow_data->background_info_waiting--;
150
151 if(control_flow_data->background_info_waiting == 0) {
152 g_debug("control flow viewer : background computation data ready.");
153
154 drawing_clear(control_flow_data->drawing);
155 processlist_clear(control_flow_data->process_list);
156 redraw_notify(control_flow_data, NULL);
157 }
158
159 return 0;
160}
161
162
163/* Request background computation. Verify if it is in progress or ready first.
164 * Only for each trace in the tab's traceset.
165 */
166void request_background_data(ControlFlowData *control_flow_data)
167{
168 LttvTracesetContext * tsc =
169 lttvwindow_get_traceset_context(control_flow_data->tab);
170 gint num_traces = lttv_traceset_number(tsc->ts);
171 gint i;
172 LttvTrace *trace;
173
174 LttvHooks *background_ready_hook =
175 lttv_hooks_new();
176 lttv_hooks_add(background_ready_hook, background_ready, control_flow_data,
177 LTTV_PRIO_DEFAULT);
178 control_flow_data->background_info_waiting = 0;
179
180 for(i=0;i<num_traces;i++) {
181 trace = lttv_traceset_get(tsc->ts, i);
182
183 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace)==FALSE) {
184
185 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
186 trace) == FALSE) {
187 /* We first remove requests that could have been done for the same
188 * information. Happens when two viewers ask for it before servicing
189 * starts.
190 */
191 lttvwindowtraces_background_request_remove(trace, "state");
192 lttvwindowtraces_background_request_queue(trace,
193 "state");
194 lttvwindowtraces_background_notify_queue(control_flow_data,
195 trace,
196 ltt_time_infinite,
197 NULL,
198 background_ready_hook);
199 control_flow_data->background_info_waiting++;
200 } else { /* in progress */
201
202 lttvwindowtraces_background_notify_current(control_flow_data,
203 trace,
204 ltt_time_infinite,
205 NULL,
206 background_ready_hook);
207 control_flow_data->background_info_waiting++;
208 }
209 }
210 }
211
212 lttv_hooks_destroy(background_ready_hook);
213}
214
215
216
217
218/**
219 * Event Viewer's constructor hook
220 *
221 * This constructor is given as a parameter to the menuitem and toolbar button
222 * registration. It creates the list.
223 * @param tab A pointer to the parent tab.
224 * @return The widget created.
225 */
226GtkWidget *
227h_guicontrolflow(Tab *tab)
228{
229 g_info("h_guicontrolflow, %p", tab);
230 ControlFlowData *control_flow_data = guicontrolflow() ;
231
232 control_flow_data->tab = tab;
233
234 //g_debug("time width2 : %u",time_window->time_width);
235 // Unreg done in the GuiControlFlow_Destructor
236 lttvwindow_register_traceset_notify(tab,
237 traceset_notify,
238 control_flow_data);
239
240 lttvwindow_register_time_window_notify(tab,
241 update_time_window_hook,
242 control_flow_data);
243 lttvwindow_register_current_time_notify(tab,
244 update_current_time_hook,
245 control_flow_data);
246 lttvwindow_register_redraw_notify(tab,
247 redraw_notify,
248 control_flow_data);
249 lttvwindow_register_continue_notify(tab,
250 continue_notify,
251 control_flow_data);
252 request_background_data(control_flow_data);
253
254
255 return guicontrolflow_get_widget(control_flow_data) ;
256
257}
258
259int event_selected_hook(void *hook_data, void *call_data)
260{
261 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
262 guint *event_number = (guint*) call_data;
263
264 g_debug("DEBUG : event selected by main window : %u", *event_number);
265
266}
267
268
269static __inline PropertiesLine prepare_line(LttvProcessState *process)
270{
271 PropertiesLine prop_line;
272 prop_line.line_width = 2;
273 prop_line.style = GDK_LINE_SOLID;
274 prop_line.y = MIDDLE;
275 //GdkColormap *colormap = gdk_colormap_get_system();
276
277 g_debug("prepare_line for state : %s", g_quark_to_string(process->state->s));
278
279 /* color of line : status of the process */
280 if(process->state->s == LTTV_STATE_UNNAMED)
281 prop_line.color = drawing_colors[COL_WHITE];
282 else if(process->state->s == LTTV_STATE_WAIT_FORK)
283 prop_line.color = drawing_colors[COL_WAIT_FORK];
284 else if(process->state->s == LTTV_STATE_WAIT_CPU)
285 prop_line.color = drawing_colors[COL_WAIT_CPU];
286 else if(process->state->s == LTTV_STATE_EXIT)
287 prop_line.color = drawing_colors[COL_EXIT];
288 else if(process->state->s == LTTV_STATE_WAIT)
289 prop_line.color = drawing_colors[COL_WAIT];
290 else if(process->state->s == LTTV_STATE_RUN)
291 prop_line.color = drawing_colors[COL_RUN];
292 else
293 prop_line.color = drawing_colors[COL_WHITE];
294
295 //gdk_colormap_alloc_color(colormap,
296 // prop_line.color,
297 // FALSE,
298 // TRUE);
299
300 return prop_line;
301
302}
303
304
305
306/* draw_before_hook
307 *
308 * This function basically draw lines and icons. Two types of lines are drawn :
309 * one small (3 pixels?) representing the state of the process and the second
310 * type is thicker (10 pixels?) representing on which CPU a process is running
311 * (and this only in running state).
312 *
313 * Extremums of the lines :
314 * x_min : time of the last event context for this process kept in memory.
315 * x_max : time of the current event.
316 * y : middle of the process in the process list. The process is found in the
317 * list, therefore is it's position in pixels.
318 *
319 * The choice of lines'color is defined by the context of the last event for this
320 * process.
321 */
322
323
324int draw_before_hook(void *hook_data, void *call_data)
325{
326 EventsRequest *events_request = (EventsRequest*)hook_data;
327 ControlFlowData *control_flow_data = events_request->viewer_data;
328 Drawing_t *drawing = control_flow_data->drawing;
329
330 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
331
332 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
333 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
334
335 LttEvent *e;
336 e = tfc->e;
337
338 LttTime evtime = ltt_event_time(e);
339 TimeWindow time_window =
340 lttvwindow_get_time_window(control_flow_data->tab);
341
342 LttTime end_time = ltt_time_add(time_window.start_time,
343 time_window.time_width);
344
345 if(ltt_time_compare(evtime, time_window.start_time) == -1
346 || ltt_time_compare(evtime, end_time) == 1)
347 return;
348
349 guint width = drawing->width;
350
351 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0) {
352
353 /* we are in a schedchange, before the state update. We must draw the
354 * items corresponding to the state before it changes : now is the right
355 * time to do it.
356 */
357
358 guint pid_out;
359 guint pid_in;
360 {
361 LttField *f = ltt_event_field(e);
362 LttField *element;
363 element = ltt_field_member(f,0);
364 pid_out = ltt_event_get_long_unsigned(e,element);
365 element = ltt_field_member(f,1);
366 pid_in = ltt_event_get_long_unsigned(e,element);
367 g_debug("out : %u in : %u", pid_out, pid_in);
368 }
369
370 {
371 /* For the pid_out */
372 /* First, check if the current process is in the state computation
373 * process list. If it is there, that means we must add it right now and
374 * draw items from the beginning of the read for it. If it is not
375 * present, it's a new process and it was not present : it will
376 * be added after the state update. */
377 LttvProcessState *process;
378 process = lttv_state_find_process(tfs, pid_out);
379
380 if(process != NULL) {
381 /* Well, the process_out existed : we must get it in the process hash
382 * or add it, and draw its items.
383 */
384 /* Add process to process list (if not present) */
385 guint y = 0, height = 0, pl_height = 0;
386 HashedProcessData *hashed_process_data = NULL;
387 ProcessList *process_list =
388 guicontrolflow_get_process_list(control_flow_data);
389 LttTime birth = process->creation_time;
390 const gchar *name = g_quark_to_string(process->name);
391
392 if(processlist_get_process_pixels(process_list,
393 pid_out,
394 &birth,
395 tfc->t_context->index,
396 &y,
397 &height,
398 &hashed_process_data) == 1)
399 {
400 /* Process not present */
401 processlist_add(process_list,
402 pid_out,
403 &birth,
404 tfc->t_context->index,
405 name,
406 &pl_height,
407 &hashed_process_data);
408 processlist_get_process_pixels(process_list,
409 pid_out,
410 &birth,
411 tfc->t_context->index,
412 &y,
413 &height,
414 &hashed_process_data);
415 drawing_insert_square( drawing, y, height);
416 }
417
418 /* Now, the process is in the state hash and our own process hash.
419 * We definitely can draw the items related to the ending state.
420 */
421
422 /* Check if the x position is unset. In can have been left unset by
423 * a draw closure from a after chunk hook. This should never happen,
424 * because it must be set by before chunk hook to the damage_begin
425 * value.
426 */
427 g_assert(hashed_process_data->x != -1);
428 {
429 guint x;
430 DrawContext draw_context;
431
432 convert_time_to_pixels(
433 time_window.start_time,
434 end_time,
435 evtime,
436 width,
437 &x);
438
439 /* Now create the drawing context that will be used to draw
440 * items related to the last state. */
441 draw_context.drawable = drawing->pixmap;
442 draw_context.gc = drawing->gc;
443 draw_context.pango_layout = drawing->pango_layout;
444 draw_context.drawinfo.start.x = hashed_process_data->x;
445 draw_context.drawinfo.end.x = x;
446
447 draw_context.drawinfo.y.over = y;
448 draw_context.drawinfo.y.middle = y+(height/4);
449 draw_context.drawinfo.y.under = y+(height/2)+2;
450
451 draw_context.drawinfo.start.offset.over = 0;
452 draw_context.drawinfo.start.offset.middle = 0;
453 draw_context.drawinfo.start.offset.under = 0;
454 draw_context.drawinfo.end.offset.over = 0;
455 draw_context.drawinfo.end.offset.middle = 0;
456 draw_context.drawinfo.end.offset.under = 0;
457
458 {
459 /* Draw the line */
460 PropertiesLine prop_line = prepare_line(process);
461 draw_line((void*)&prop_line, (void*)&draw_context);
462
463 }
464 /* become the last x position */
465 hashed_process_data->x = x;
466 }
467 }
468 }
469
470 {
471 /* For the pid_in */
472 /* First, check if the current process is in the state computation
473 * process list. If it is there, that means we must add it right now and
474 * draw items from the beginning of the read for it. If it is not
475 * present, it's a new process and it was not present : it will
476 * be added after the state update. */
477 LttvProcessState *process;
478 process = lttv_state_find_process(tfs, pid_in);
479
480 if(process != NULL) {
481 /* Well, the process_out existed : we must get it in the process hash
482 * or add it, and draw its items.
483 */
484 /* Add process to process list (if not present) */
485 guint y = 0, height = 0, pl_height = 0;
486 HashedProcessData *hashed_process_data = NULL;
487 ProcessList *process_list =
488 guicontrolflow_get_process_list(control_flow_data);
489 LttTime birth = process->creation_time;
490 const gchar *name = g_quark_to_string(process->name);
491
492 if(processlist_get_process_pixels(process_list,
493 pid_in,
494 &birth,
495 tfc->t_context->index,
496 &y,
497 &height,
498 &hashed_process_data) == 1)
499 {
500 /* Process not present */
501 processlist_add(process_list,
502 pid_in,
503 &birth,
504 tfc->t_context->index,
505 name,
506 &pl_height,
507 &hashed_process_data);
508 processlist_get_process_pixels(process_list,
509 pid_in,
510 &birth,
511 tfc->t_context->index,
512 &y,
513 &height,
514 &hashed_process_data);
515 drawing_insert_square( drawing, y, height);
516 }
517
518 /* Now, the process is in the state hash and our own process hash.
519 * We definitely can draw the items related to the ending state.
520 */
521
522 /* Check if the x position is unset. In can have been left unset by
523 * a draw closure from a after chunk hook. This should never happen,
524 * because it must be set by before chunk hook to the damage_begin
525 * value.
526 */
527 g_assert(hashed_process_data->x != -1);
528 {
529 guint x;
530 DrawContext draw_context;
531
532 convert_time_to_pixels(
533 time_window.start_time,
534 end_time,
535 evtime,
536 width,
537 &x);
538
539 /* Now create the drawing context that will be used to draw
540 * items related to the last state. */
541 draw_context.drawable = drawing->pixmap;
542 draw_context.gc = drawing->gc;
543 draw_context.pango_layout = drawing->pango_layout;
544 draw_context.drawinfo.start.x = hashed_process_data->x;
545 draw_context.drawinfo.end.x = x;
546
547 draw_context.drawinfo.y.over = y;
548 draw_context.drawinfo.y.middle = y+(height/4);
549 draw_context.drawinfo.y.under = y+(height/2)+2;
550
551 draw_context.drawinfo.start.offset.over = 0;
552 draw_context.drawinfo.start.offset.middle = 0;
553 draw_context.drawinfo.start.offset.under = 0;
554 draw_context.drawinfo.end.offset.over = 0;
555 draw_context.drawinfo.end.offset.middle = 0;
556 draw_context.drawinfo.end.offset.under = 0;
557
558 {
559 /* Draw the line */
560 PropertiesLine prop_line = prepare_line(process);
561 draw_line((void*)&prop_line, (void*)&draw_context);
562 }
563
564
565 /* become the last x position */
566 hashed_process_data->x = x;
567 }
568 }
569 }
570 } else if(strcmp(
571 ltt_eventtype_name(ltt_event_eventtype(e)),"process") == 0) {
572 /* We are in a fork or exit event */
573
574
575 }
576
577
578 return 0;
579
580
581#if 0
582 EventsRequest *events_request = (EventsRequest*)hook_data;
583 ControlFlowData *control_flow_data =
584 (ControlFlowData*)events_request->viewer_data;
585 Tab *tab = control_flow_data->tab;
586
587 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
588
589 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
590 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
591
592 LttEvent *e;
593 e = tfc->e;
594
595 LttTime evtime = ltt_event_time(e);
596 TimeWindow time_window =
597 lttvwindow_get_time_window(tab);
598
599 LttTime end_time = ltt_time_add(time_window.start_time,
600 time_window.time_width);
601 //if(time < time_beg || time > time_end) return;
602 if(ltt_time_compare(evtime, time_window.start_time) == -1
603 || ltt_time_compare(evtime, end_time) == 1)
604 return;
605
606 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0)
607 {
608 g_debug("schedchange!");
609
610 /* Add process to process list (if not present) and get drawing "y" from
611 * process position */
612 guint pid_out, pid_in;
613 LttvProcessState *process_out, *process_in;
614 LttTime birth;
615 guint y_in = 0, y_out = 0, height = 0, pl_height = 0;
616
617 ProcessList *process_list =
618 guicontrolflow_get_process_list(control_flow_data);
619
620
621 LttField *f = ltt_event_field(e);
622 LttField *element;
623 element = ltt_field_member(f,0);
624 pid_out = ltt_event_get_long_unsigned(e,element);
625 element = ltt_field_member(f,1);
626 pid_in = ltt_event_get_long_unsigned(e,element);
627 g_debug("out : %u in : %u", pid_out, pid_in);
628
629
630 /* Find process pid_out in the list... */
631 process_out = lttv_state_find_process(tfs, pid_out);
632 if(process_out == NULL) return 0;
633 g_debug("out : %s",g_quark_to_string(process_out->state->s));
634
635 birth = process_out->creation_time;
636 const gchar *name = g_quark_to_string(process_out->name);
637 HashedProcessData *hashed_process_data_out = NULL;
638
639 if(processlist_get_process_pixels(process_list,
640 pid_out,
641 &birth,
642 tfc->t_context->index,
643 &y_out,
644 &height,
645 &hashed_process_data_out) == 1)
646 {
647 /* Process not present */
648 processlist_add(process_list,
649 pid_out,
650 &birth,
651 tfc->t_context->index,
652 name,
653 &pl_height,
654 &hashed_process_data_out);
655 g_assert(processlist_get_process_pixels(process_list,
656 pid_out,
657 &birth,
658 tfc->t_context->index,
659 &y_out,
660 &height,
661 &hashed_process_data_out)==0);
662 drawing_insert_square( control_flow_data->drawing, y_out, height);
663 }
664 //g_free(name);
665
666 /* Find process pid_in in the list... */
667 process_in = lttv_state_find_process(tfs, pid_in);
668 if(process_in == NULL) return 0;
669 g_debug("in : %s",g_quark_to_string(process_in->state->s));
670
671 birth = process_in->creation_time;
672 name = g_quark_to_string(process_in->name);
673 HashedProcessData *hashed_process_data_in = NULL;
674
675 if(processlist_get_process_pixels(process_list,
676 pid_in,
677 &birth,
678 tfc->t_context->index,
679 &y_in,
680 &height,
681 &hashed_process_data_in) == 1)
682 {
683 /* Process not present */
684 processlist_add(process_list,
685 pid_in,
686 &birth,
687 tfc->t_context->index,
688 name,
689 &pl_height,
690 &hashed_process_data_in);
691 processlist_get_process_pixels(process_list,
692 pid_in,
693 &birth,
694 tfc->t_context->index,
695 &y_in,
696 &height,
697 &hashed_process_data_in);
698
699 drawing_insert_square( control_flow_data->drawing, y_in, height);
700 }
701 //g_free(name);
702
703
704 /* Find pixels corresponding to time of the event. If the time does
705 * not fit in the window, show a warning, not supposed to happend. */
706 guint x = 0;
707 guint width = control_flow_data->drawing->width;
708
709 LttTime time = ltt_event_time(e);
710
711 LttTime window_end = ltt_time_add(time_window.time_width,
712 time_window.start_time);
713
714
715 convert_time_to_pixels(
716 time_window.start_time,
717 window_end,
718 time,
719 width,
720 &x);
721 //assert(x <= width);
722 //
723 /* draw what represents the event for outgoing process. */
724
725 DrawContext *draw_context_out = hashed_process_data_out->draw_context;
726 draw_context_out->current->modify_over->x = x;
727 draw_context_out->current->modify_under->x = x;
728 draw_context_out->current->modify_over->y = y_out;
729 draw_context_out->current->modify_under->y = y_out+(height/2)+2;
730 draw_context_out->drawable = control_flow_data->drawing->pixmap;
731 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
732 GtkWidget *widget = control_flow_data->drawing->drawing_area;
733 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
734 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
735 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
736 //draw_context_out->gc = widget->style->black_gc;
737
738 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
739 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
740
741 /* Draw the line/background of the out process */
742 if(draw_context_out->previous->middle->x == -1)
743 {
744 draw_context_out->previous->over->x =
745 control_flow_data->drawing->damage_begin;
746 draw_context_out->previous->middle->x =
747 control_flow_data->drawing->damage_begin;
748 draw_context_out->previous->under->x =
749 control_flow_data->drawing->damage_begin;
750
751 g_debug("out middle x_beg : %u",control_flow_data->drawing->damage_begin);
752 }
753
754 draw_context_out->current->middle->x = x;
755 draw_context_out->current->over->x = x;
756 draw_context_out->current->under->x = x;
757 draw_context_out->current->middle->y = y_out + height/2;
758 draw_context_out->current->over->y = y_out;
759 draw_context_out->current->under->y = y_out + height;
760 draw_context_out->previous->middle->y = y_out + height/2;
761 draw_context_out->previous->over->y = y_out;
762 draw_context_out->previous->under->y = y_out + height;
763
764 draw_context_out->drawable = control_flow_data->drawing->pixmap;
765 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
766
767 if(process_out->state->s == LTTV_STATE_RUN)
768 {
769 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
770 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
771 draw_context_out->gc = control_flow_data->drawing->gc;
772
773 PropertiesBG prop_bg;
774 prop_bg.color = g_new(GdkColor,1);
775
776 switch(tfc->index) {
777 case 0:
778 prop_bg.color->red = 0x1515;
779 prop_bg.color->green = 0x1515;
780 prop_bg.color->blue = 0x8c8c;
781 break;
782 case 1:
783 prop_bg.color->red = 0x4e4e;
784 prop_bg.color->green = 0xa9a9;
785 prop_bg.color->blue = 0xa4a4;
786 break;
787 case 2:
788 prop_bg.color->red = 0x7a7a;
789 prop_bg.color->green = 0x4a4a;
790 prop_bg.color->blue = 0x8b8b;
791 break;
792 case 3:
793 prop_bg.color->red = 0x8080;
794 prop_bg.color->green = 0x7777;
795 prop_bg.color->blue = 0x4747;
796 break;
797 default:
798 prop_bg.color->red = 0xe7e7;
799 prop_bg.color->green = 0xe7e7;
800 prop_bg.color->blue = 0xe7e7;
801 }
802
803 g_debug("calling from draw_event");
804 draw_bg((void*)&prop_bg, (void*)draw_context_out);
805 g_free(prop_bg.color);
806 //gdk_gc_unref(draw_context_out->gc);
807 }
808
809 draw_context_out->gc = widget->style->black_gc;
810
811 GdkColor colorfg_out = { 0, 0xffff, 0x0000, 0x0000 };
812 GdkColor colorbg_out = { 0, 0x0000, 0x0000, 0x0000 };
813 PropertiesText prop_text_out;
814 prop_text_out.foreground = &colorfg_out;
815 prop_text_out.background = &colorbg_out;
816 prop_text_out.size = 6;
817 prop_text_out.position = OVER;
818
819 /* color of text : status of the process */
820 if(process_out->state->s == LTTV_STATE_UNNAMED)
821 {
822 prop_text_out.foreground->red = 0xffff;
823 prop_text_out.foreground->green = 0xffff;
824 prop_text_out.foreground->blue = 0xffff;
825 }
826 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
827 {
828 prop_text_out.foreground->red = 0x0fff;
829 prop_text_out.foreground->green = 0xffff;
830 prop_text_out.foreground->blue = 0xfff0;
831 }
832 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
833 {
834 prop_text_out.foreground->red = 0xffff;
835 prop_text_out.foreground->green = 0xffff;
836 prop_text_out.foreground->blue = 0x0000;
837 }
838 else if(process_out->state->s == LTTV_STATE_EXIT)
839 {
840 prop_text_out.foreground->red = 0xffff;
841 prop_text_out.foreground->green = 0x0000;
842 prop_text_out.foreground->blue = 0xffff;
843 }
844 else if(process_out->state->s == LTTV_STATE_WAIT)
845 {
846 prop_text_out.foreground->red = 0xffff;
847 prop_text_out.foreground->green = 0x0000;
848 prop_text_out.foreground->blue = 0x0000;
849 }
850 else if(process_out->state->s == LTTV_STATE_RUN)
851 {
852 prop_text_out.foreground->red = 0x0000;
853 prop_text_out.foreground->green = 0xffff;
854 prop_text_out.foreground->blue = 0x0000;
855 }
856 else
857 {
858 prop_text_out.foreground->red = 0xffff;
859 prop_text_out.foreground->green = 0xffff;
860 prop_text_out.foreground->blue = 0xffff;
861 }
862
863
864 /* Print status of the process : U, WF, WC, E, W, R */
865 if(process_out->state->s == LTTV_STATE_UNNAMED)
866 prop_text_out.text = "U->";
867 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
868 prop_text_out.text = "WF->";
869 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
870 prop_text_out.text = "WC->";
871 else if(process_out->state->s == LTTV_STATE_EXIT)
872 prop_text_out.text = "E->";
873 else if(process_out->state->s == LTTV_STATE_WAIT)
874 prop_text_out.text = "W->";
875 else if(process_out->state->s == LTTV_STATE_RUN)
876 prop_text_out.text = "R->";
877 else
878 prop_text_out.text = "U";
879
880 draw_text((void*)&prop_text_out, (void*)draw_context_out);
881 //gdk_gc_unref(draw_context_out->gc);
882
883 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
884 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
885 draw_context_out->gc = control_flow_data->drawing->gc;
886
887 PropertiesLine prop_line_out;
888 prop_line_out.color = g_new(GdkColor,1);
889 prop_line_out.line_width = 2;
890 prop_line_out.style = GDK_LINE_SOLID;
891 prop_line_out.position = MIDDLE;
892
893 g_debug("out state : %s", g_quark_to_string(process_out->state->s));
894
895 /* color of line : status of the process */
896 if(process_out->state->s == LTTV_STATE_UNNAMED)
897 {
898 prop_line_out.color->red = 0xffff;
899 prop_line_out.color->green = 0xffff;
900 prop_line_out.color->blue = 0xffff;
901 }
902 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
903 {
904 prop_line_out.color->red = 0x0fff;
905 prop_line_out.color->green = 0xffff;
906 prop_line_out.color->blue = 0xfff0;
907 }
908 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
909 {
910 prop_line_out.color->red = 0xffff;
911 prop_line_out.color->green = 0xffff;
912 prop_line_out.color->blue = 0x0000;
913 }
914 else if(process_out->state->s == LTTV_STATE_EXIT)
915 {
916 prop_line_out.color->red = 0xffff;
917 prop_line_out.color->green = 0x0000;
918 prop_line_out.color->blue = 0xffff;
919 }
920 else if(process_out->state->s == LTTV_STATE_WAIT)
921 {
922 prop_line_out.color->red = 0xffff;
923 prop_line_out.color->green = 0x0000;
924 prop_line_out.color->blue = 0x0000;
925 }
926 else if(process_out->state->s == LTTV_STATE_RUN)
927 {
928 prop_line_out.color->red = 0x0000;
929 prop_line_out.color->green = 0xffff;
930 prop_line_out.color->blue = 0x0000;
931 }
932 else
933 {
934 prop_line_out.color->red = 0xffff;
935 prop_line_out.color->green = 0xffff;
936 prop_line_out.color->blue = 0xffff;
937 }
938
939 draw_line((void*)&prop_line_out, (void*)draw_context_out);
940 g_free(prop_line_out.color);
941 //gdk_gc_unref(draw_context_out->gc);
942 /* Note : finishing line will have to be added when trace read over. */
943
944 /* Finally, update the drawing context of the pid_in. */
945
946 DrawContext *draw_context_in = hashed_process_data_in->draw_context;
947 draw_context_in->current->modify_over->x = x;
948 draw_context_in->current->modify_under->x = x;
949 draw_context_in->current->modify_over->y = y_in;
950 draw_context_in->current->modify_under->y = y_in+(height/2)+2;
951 draw_context_in->drawable = control_flow_data->drawing->pixmap;
952 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
953 widget = control_flow_data->drawing->drawing_area;
954 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
955 //draw_context_in->gc = widget->style->black_gc;
956 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
957 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
958
959 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
960 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
961
962 /* Draw the line/bg of the in process */
963 if(draw_context_in->previous->middle->x == -1)
964 {
965 draw_context_in->previous->over->x =
966 control_flow_data->drawing->damage_begin;
967 draw_context_in->previous->middle->x =
968 control_flow_data->drawing->damage_begin;
969 draw_context_in->previous->under->x =
970 control_flow_data->drawing->damage_begin;
971
972 g_debug("in middle x_beg : %u",control_flow_data->drawing->damage_begin);
973
974 }
975
976 draw_context_in->current->middle->x = x;
977 draw_context_in->current->over->x = x;
978 draw_context_in->current->under->x = x;
979 draw_context_in->current->middle->y = y_in + height/2;
980 draw_context_in->current->over->y = y_in;
981 draw_context_in->current->under->y = y_in + height;
982 draw_context_in->previous->middle->y = y_in + height/2;
983 draw_context_in->previous->over->y = y_in;
984 draw_context_in->previous->under->y = y_in + height;
985
986 draw_context_in->drawable = control_flow_data->drawing->pixmap;
987 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
988
989
990 if(process_in->state->s == LTTV_STATE_RUN)
991 {
992 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
993 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
994 draw_context_in->gc = control_flow_data->drawing->gc;
995
996 PropertiesBG prop_bg;
997 prop_bg.color = g_new(GdkColor,1);
998
999 switch(tfc->index) {
1000 case 0:
1001 prop_bg.color->red = 0x1515;
1002 prop_bg.color->green = 0x1515;
1003 prop_bg.color->blue = 0x8c8c;
1004 break;
1005 case 1:
1006 prop_bg.color->red = 0x4e4e;
1007 prop_bg.color->green = 0xa9a9;
1008 prop_bg.color->blue = 0xa4a4;
1009 break;
1010 case 2:
1011 prop_bg.color->red = 0x7a7a;
1012 prop_bg.color->green = 0x4a4a;
1013 prop_bg.color->blue = 0x8b8b;
1014 break;
1015 case 3:
1016 prop_bg.color->red = 0x8080;
1017 prop_bg.color->green = 0x7777;
1018 prop_bg.color->blue = 0x4747;
1019 break;
1020 default:
1021 prop_bg.color->red = 0xe7e7;
1022 prop_bg.color->green = 0xe7e7;
1023 prop_bg.color->blue = 0xe7e7;
1024 }
1025
1026
1027 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1028 g_free(prop_bg.color);
1029 //gdk_gc_unref(draw_context_in->gc);
1030 }
1031
1032 draw_context_in->gc = widget->style->black_gc;
1033
1034 GdkColor colorfg_in = { 0, 0x0000, 0xffff, 0x0000 };
1035 GdkColor colorbg_in = { 0, 0x0000, 0x0000, 0x0000 };
1036 PropertiesText prop_text_in;
1037 prop_text_in.foreground = &colorfg_in;
1038 prop_text_in.background = &colorbg_in;
1039 prop_text_in.size = 6;
1040 prop_text_in.position = OVER;
1041
1042 g_debug("in state : %s", g_quark_to_string(process_in->state->s));
1043 /* foreground of text : status of the process */
1044 if(process_in->state->s == LTTV_STATE_UNNAMED)
1045 {
1046 prop_text_in.foreground->red = 0xffff;
1047 prop_text_in.foreground->green = 0xffff;
1048 prop_text_in.foreground->blue = 0xffff;
1049 }
1050 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1051 {
1052 prop_text_in.foreground->red = 0x0fff;
1053 prop_text_in.foreground->green = 0xffff;
1054 prop_text_in.foreground->blue = 0xfff0;
1055 }
1056 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1057 {
1058 prop_text_in.foreground->red = 0xffff;
1059 prop_text_in.foreground->green = 0xffff;
1060 prop_text_in.foreground->blue = 0x0000;
1061 }
1062 else if(process_in->state->s == LTTV_STATE_EXIT)
1063 {
1064 prop_text_in.foreground->red = 0xffff;
1065 prop_text_in.foreground->green = 0x0000;
1066 prop_text_in.foreground->blue = 0xffff;
1067 }
1068 else if(process_in->state->s == LTTV_STATE_WAIT)
1069 {
1070 prop_text_in.foreground->red = 0xffff;
1071 prop_text_in.foreground->green = 0x0000;
1072 prop_text_in.foreground->blue = 0x0000;
1073 }
1074 else if(process_in->state->s == LTTV_STATE_RUN)
1075 {
1076 prop_text_in.foreground->red = 0x0000;
1077 prop_text_in.foreground->green = 0xffff;
1078 prop_text_in.foreground->blue = 0x0000;
1079 }
1080 else
1081 {
1082 prop_text_in.foreground->red = 0xffff;
1083 prop_text_in.foreground->green = 0xffff;
1084 prop_text_in.foreground->blue = 0xffff;
1085 }
1086
1087
1088
1089 /* Print status of the process : U, WF, WC, E, W, R */
1090 if(process_in->state->s == LTTV_STATE_UNNAMED)
1091 prop_text_in.text = "U->";
1092 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1093 prop_text_in.text = "WF->";
1094 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1095 prop_text_in.text = "WC->";
1096 else if(process_in->state->s == LTTV_STATE_EXIT)
1097 prop_text_in.text = "E->";
1098 else if(process_in->state->s == LTTV_STATE_WAIT)
1099 prop_text_in.text = "W->";
1100 else if(process_in->state->s == LTTV_STATE_RUN)
1101 prop_text_in.text = "R->";
1102 else
1103 prop_text_in.text = "U";
1104
1105 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1106 //gdk_gc_unref(draw_context_in->gc);
1107
1108 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1109 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1110 draw_context_in->gc = control_flow_data->drawing->gc;
1111
1112 PropertiesLine prop_line_in;
1113 prop_line_in.color = g_new(GdkColor,1);
1114 prop_line_in.line_width = 2;
1115 prop_line_in.style = GDK_LINE_SOLID;
1116 prop_line_in.position = MIDDLE;
1117
1118 /* color of line : status of the process */
1119 if(process_in->state->s == LTTV_STATE_UNNAMED)
1120 {
1121 prop_line_in.color->red = 0xffff;
1122 prop_line_in.color->green = 0xffff;
1123 prop_line_in.color->blue = 0xffff;
1124 }
1125 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1126 {
1127 prop_line_in.color->red = 0x0fff;
1128 prop_line_in.color->green = 0xffff;
1129 prop_line_in.color->blue = 0xfff0;
1130 }
1131 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1132 {
1133 prop_line_in.color->red = 0xffff;
1134 prop_line_in.color->green = 0xffff;
1135 prop_line_in.color->blue = 0x0000;
1136 }
1137 else if(process_in->state->s == LTTV_STATE_EXIT)
1138 {
1139 prop_line_in.color->red = 0xffff;
1140 prop_line_in.color->green = 0x0000;
1141 prop_line_in.color->blue = 0xffff;
1142 }
1143 else if(process_in->state->s == LTTV_STATE_WAIT)
1144 {
1145 prop_line_in.color->red = 0xffff;
1146 prop_line_in.color->green = 0x0000;
1147 prop_line_in.color->blue = 0x0000;
1148 }
1149 else if(process_in->state->s == LTTV_STATE_RUN)
1150 {
1151 prop_line_in.color->red = 0x0000;
1152 prop_line_in.color->green = 0xffff;
1153 prop_line_in.color->blue = 0x0000;
1154 }
1155 else
1156 {
1157 prop_line_in.color->red = 0xffff;
1158 prop_line_in.color->green = 0xffff;
1159 prop_line_in.color->blue = 0xffff;
1160 }
1161
1162 draw_line((void*)&prop_line_in, (void*)draw_context_in);
1163 g_free(prop_line_in.color);
1164 //gdk_gc_unref(draw_context_in->gc);
1165 }
1166
1167 return 0;
1168#endif //0
1169
1170
1171
1172 /* Text dump */
1173#ifdef DONTSHOW
1174 GString *string = g_string_new("");;
1175 gboolean field_names = TRUE, state = TRUE;
1176
1177 lttv_event_to_string(e, tfc->tf, string, TRUE, field_names, tfs);
1178 g_string_append_printf(string,"\n");
1179
1180 if(state) {
1181 g_string_append_printf(string, " %s",
1182 g_quark_to_string(tfs->process->state->s));
1183 }
1184
1185 g_info("%s",string->str);
1186
1187 g_string_free(string, TRUE);
1188
1189 /* End of text dump */
1190#endif //DONTSHOW
1191
1192}
1193
1194/* draw_after_hook
1195 *
1196 * The draw after hook is called by the reading API to have a
1197 * particular event drawn on the screen.
1198 * @param hook_data ControlFlowData structure of the viewer.
1199 * @param call_data Event context.
1200 *
1201 * This function adds items to be drawn in a queue for each process.
1202 *
1203 */
1204int draw_after_hook(void *hook_data, void *call_data)
1205{
1206 EventsRequest *events_request = (EventsRequest*)hook_data;
1207 ControlFlowData *control_flow_data = events_request->viewer_data;
1208
1209 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1210
1211 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1212 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
1213
1214 LttEvent *e;
1215 e = tfc->e;
1216
1217 LttTime evtime = ltt_event_time(e);
1218 TimeWindow time_window =
1219 lttvwindow_get_time_window(control_flow_data->tab);
1220
1221 LttTime end_time = ltt_time_add(time_window.start_time,
1222 time_window.time_width);
1223
1224 if(ltt_time_compare(evtime, time_window.start_time) == -1
1225 || ltt_time_compare(evtime, end_time) == 1)
1226 return;
1227
1228 guint width = control_flow_data->drawing->width;
1229
1230 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0) {
1231
1232 g_debug("schedchange!");
1233
1234 {
1235 /* Add process to process list (if not present) */
1236 LttvProcessState *process_out, *process_in;
1237 LttTime birth;
1238 guint y_in = 0, y_out = 0, height = 0, pl_height = 0;
1239 HashedProcessData *hashed_process_data_in = NULL;
1240
1241 ProcessList *process_list =
1242 guicontrolflow_get_process_list(control_flow_data);
1243
1244 guint pid_in;
1245 {
1246 guint pid_out;
1247 LttField *f = ltt_event_field(e);
1248 LttField *element;
1249 element = ltt_field_member(f,0);
1250 pid_out = ltt_event_get_long_unsigned(e,element);
1251 element = ltt_field_member(f,1);
1252 pid_in = ltt_event_get_long_unsigned(e,element);
1253 g_debug("out : %u in : %u", pid_out, pid_in);
1254 }
1255
1256
1257 /* Find process pid_in in the list... */
1258 process_in = lttv_state_find_process(tfs, pid_in);
1259 /* It should exist, because we are after the state update. */
1260 g_assert(process_in != NULL);
1261
1262 birth = process_in->creation_time;
1263 const gchar *name = g_quark_to_string(process_in->name);
1264
1265 if(processlist_get_process_pixels(process_list,
1266 pid_in,
1267 &birth,
1268 tfc->t_context->index,
1269 &y_in,
1270 &height,
1271 &hashed_process_data_in) == 1)
1272 {
1273 /* Process not present */
1274 processlist_add(process_list,
1275 pid_in,
1276 &birth,
1277 tfc->t_context->index,
1278 name,
1279 &pl_height,
1280 &hashed_process_data_in);
1281 processlist_get_process_pixels(process_list,
1282 pid_in,
1283 &birth,
1284 tfc->t_context->index,
1285 &y_in,
1286 &height,
1287 &hashed_process_data_in);
1288 drawing_insert_square( control_flow_data->drawing, y_in, height);
1289 }
1290
1291 convert_time_to_pixels(
1292 time_window.start_time,
1293 end_time,
1294 evtime,
1295 width,
1296 &hashed_process_data_in->x);
1297 }
1298 } else if(strcmp(
1299 ltt_eventtype_name(ltt_event_eventtype(e)),"process") == 0) {
1300 /* We are in a fork or exit event */
1301
1302
1303 }
1304
1305 return 0;
1306
1307
1308
1309#if 0
1310 EventsRequest *events_request = (EventsRequest*)hook_data;
1311 ControlFlowData *control_flow_data = events_request->viewer_data;
1312
1313 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1314
1315 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1316 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
1317
1318
1319 LttEvent *e;
1320 e = tfc->e;
1321
1322 LttTime evtime = ltt_event_time(e);
1323 TimeWindow time_window =
1324 lttvwindow_get_time_window(control_flow_data->tab);
1325
1326 LttTime end_time = ltt_time_add(time_window.start_time,
1327 time_window.time_width);
1328 //if(time < time_beg || time > time_end) return;
1329 if(ltt_time_compare(evtime, time_window.start_time) == -1
1330 || ltt_time_compare(evtime, end_time) == 1)
1331 return;
1332
1333
1334 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0)
1335 {
1336 g_debug("schedchange!");
1337
1338 /* Add process to process list (if not present) and get drawing "y" from
1339 * process position */
1340 guint pid_out, pid_in;
1341 LttvProcessState *process_out, *process_in;
1342 LttTime birth;
1343 guint y_in = 0, y_out = 0, height = 0, pl_height = 0;
1344
1345 ProcessList *process_list =
1346 guicontrolflow_get_process_list(control_flow_data);
1347
1348
1349 LttField *f = ltt_event_field(e);
1350 LttField *element;
1351 element = ltt_field_member(f,0);
1352 pid_out = ltt_event_get_long_unsigned(e,element);
1353 element = ltt_field_member(f,1);
1354 pid_in = ltt_event_get_long_unsigned(e,element);
1355 //g_debug("out : %u in : %u", pid_out, pid_in);
1356
1357
1358 /* Find process pid_out in the list... */
1359 process_out = lttv_state_find_process(tfs, pid_out);
1360 if(process_out == NULL) return 0;
1361 //g_debug("out : %s",g_quark_to_string(process_out->state->s));
1362
1363 birth = process_out->creation_time;
1364 gchar *name = strdup(g_quark_to_string(process_out->name));
1365 HashedProcessData *hashed_process_data_out = NULL;
1366
1367 if(processlist_get_process_pixels(process_list,
1368 pid_out,
1369 &birth,
1370 tfc->t_context->index,
1371 &y_out,
1372 &height,
1373 &hashed_process_data_out) == 1)
1374 {
1375 /* Process not present */
1376 processlist_add(process_list,
1377 pid_out,
1378 &birth,
1379 tfc->t_context->index,
1380 name,
1381 &pl_height,
1382 &hashed_process_data_out);
1383 processlist_get_process_pixels(process_list,
1384 pid_out,
1385 &birth,
1386 tfc->t_context->index,
1387 &y_out,
1388 &height,
1389 &hashed_process_data_out);
1390 drawing_insert_square( control_flow_data->drawing, y_out, height);
1391 }
1392
1393 g_free(name);
1394
1395 /* Find process pid_in in the list... */
1396 process_in = lttv_state_find_process(tfs, pid_in);
1397 if(process_in == NULL) return 0;
1398 //g_debug("in : %s",g_quark_to_string(process_in->state->s));
1399
1400 birth = process_in->creation_time;
1401 name = strdup(g_quark_to_string(process_in->name));
1402 HashedProcessData *hashed_process_data_in = NULL;
1403
1404 if(processlist_get_process_pixels(process_list,
1405 pid_in,
1406 &birth,
1407 tfc->t_context->index,
1408 &y_in,
1409 &height,
1410 &hashed_process_data_in) == 1)
1411 {
1412 /* Process not present */
1413 processlist_add(process_list,
1414 pid_in,
1415 &birth,
1416 tfc->t_context->index,
1417 name,
1418 &pl_height,
1419 &hashed_process_data_in);
1420 processlist_get_process_pixels(process_list,
1421 pid_in,
1422 &birth,
1423 tfc->t_context->index,
1424 &y_in,
1425 &height,
1426 &hashed_process_data_in);
1427
1428 drawing_insert_square( control_flow_data->drawing, y_in, height);
1429 }
1430 g_free(name);
1431
1432
1433 /* Find pixels corresponding to time of the event. If the time does
1434 * not fit in the window, show a warning, not supposed to happend. */
1435 //guint x = 0;
1436 //guint width = control_flow_data->drawing->drawing_area->allocation.width;
1437
1438 //LttTime time = ltt_event_time(e);
1439
1440 //LttTime window_end = ltt_time_add(time_window->time_width,
1441 // time_window->start_time);
1442
1443
1444 //convert_time_to_pixels(
1445 // time_window->start_time,
1446 // window_end,
1447 // time,
1448 // width,
1449 // &x);
1450
1451 //assert(x <= width);
1452
1453 /* draw what represents the event for outgoing process. */
1454
1455 DrawContext *draw_context_out = hashed_process_data_out->draw_context;
1456 //draw_context_out->current->modify_over->x = x;
1457 draw_context_out->current->modify_over->y = y_out;
1458 draw_context_out->current->modify_under->y = y_out+(height/2)+2;
1459 draw_context_out->drawable = control_flow_data->drawing->pixmap;
1460 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
1461 GtkWidget *widget = control_flow_data->drawing->drawing_area;
1462 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1463
1464 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
1465 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1466
1467 /*if(process_out->state->s == LTTV_STATE_RUN)
1468 {
1469 draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1470 gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
1471 PropertiesBG prop_bg;
1472 prop_bg.color = g_new(GdkColor,1);
1473
1474 prop_bg.color->red = 0xffff;
1475 prop_bg.color->green = 0xffff;
1476 prop_bg.color->blue = 0xffff;
1477
1478 draw_bg((void*)&prop_bg, (void*)draw_context_out);
1479 g_free(prop_bg.color);
1480 gdk_gc_unref(draw_context_out->gc);
1481 }*/
1482
1483 draw_context_out->gc = widget->style->black_gc;
1484
1485 GdkColor colorfg_out = { 0, 0xffff, 0x0000, 0x0000 };
1486 GdkColor colorbg_out = { 0, 0x0000, 0x0000, 0x0000 };
1487 PropertiesText prop_text_out;
1488 prop_text_out.foreground = &colorfg_out;
1489 prop_text_out.background = &colorbg_out;
1490 prop_text_out.size = 6;
1491 prop_text_out.position = OVER;
1492
1493 /* color of text : status of the process */
1494 if(process_out->state->s == LTTV_STATE_UNNAMED)
1495 {
1496 prop_text_out.foreground->red = 0xffff;
1497 prop_text_out.foreground->green = 0xffff;
1498 prop_text_out.foreground->blue = 0xffff;
1499 }
1500 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1501 {
1502 prop_text_out.foreground->red = 0x0fff;
1503 prop_text_out.foreground->green = 0xffff;
1504 prop_text_out.foreground->blue = 0xfff0;
1505 }
1506 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1507 {
1508 prop_text_out.foreground->red = 0xffff;
1509 prop_text_out.foreground->green = 0xffff;
1510 prop_text_out.foreground->blue = 0x0000;
1511 }
1512 else if(process_out->state->s == LTTV_STATE_EXIT)
1513 {
1514 prop_text_out.foreground->red = 0xffff;
1515 prop_text_out.foreground->green = 0x0000;
1516 prop_text_out.foreground->blue = 0xffff;
1517 }
1518 else if(process_out->state->s == LTTV_STATE_WAIT)
1519 {
1520 prop_text_out.foreground->red = 0xffff;
1521 prop_text_out.foreground->green = 0x0000;
1522 prop_text_out.foreground->blue = 0x0000;
1523 }
1524 else if(process_out->state->s == LTTV_STATE_RUN)
1525 {
1526 prop_text_out.foreground->red = 0x0000;
1527 prop_text_out.foreground->green = 0xffff;
1528 prop_text_out.foreground->blue = 0x0000;
1529 }
1530 else
1531 {
1532 prop_text_out.foreground->red = 0xffff;
1533 prop_text_out.foreground->green = 0xffff;
1534 prop_text_out.foreground->blue = 0xffff;
1535 }
1536
1537 /* Print status of the process : U, WF, WC, E, W, R */
1538 if(process_out->state->s == LTTV_STATE_UNNAMED)
1539 prop_text_out.text = "U";
1540 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1541 prop_text_out.text = "WF";
1542 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1543 prop_text_out.text = "WC";
1544 else if(process_out->state->s == LTTV_STATE_EXIT)
1545 prop_text_out.text = "E";
1546 else if(process_out->state->s == LTTV_STATE_WAIT)
1547 prop_text_out.text = "W";
1548 else if(process_out->state->s == LTTV_STATE_RUN)
1549 prop_text_out.text = "R";
1550 else
1551 prop_text_out.text = "U";
1552
1553 draw_text((void*)&prop_text_out, (void*)draw_context_out);
1554
1555 //gdk_gc_unref(draw_context_out->gc);
1556
1557 draw_context_out->current->middle->y = y_out+height/2;
1558 draw_context_out->current->over->y = y_out;
1559 draw_context_out->current->under->y = y_out+height;
1560 draw_context_out->current->status = process_out->state->s;
1561
1562 /* for pid_out : remove previous, Prev = current, new current (default) */
1563 g_free(draw_context_out->previous->modify_under);
1564 g_free(draw_context_out->previous->modify_middle);
1565 g_free(draw_context_out->previous->modify_over);
1566 g_free(draw_context_out->previous->under);
1567 g_free(draw_context_out->previous->middle);
1568 g_free(draw_context_out->previous->over);
1569 g_free(draw_context_out->previous);
1570
1571 draw_context_out->previous = draw_context_out->current;
1572
1573 draw_context_out->current = g_new(DrawInfo,1);
1574 draw_context_out->current->over = g_new(ItemInfo,1);
1575 draw_context_out->current->over->x = -1;
1576 draw_context_out->current->over->y = -1;
1577 draw_context_out->current->middle = g_new(ItemInfo,1);
1578 draw_context_out->current->middle->x = -1;
1579 draw_context_out->current->middle->y = -1;
1580 draw_context_out->current->under = g_new(ItemInfo,1);
1581 draw_context_out->current->under->x = -1;
1582 draw_context_out->current->under->y = -1;
1583 draw_context_out->current->modify_over = g_new(ItemInfo,1);
1584 draw_context_out->current->modify_over->x = -1;
1585 draw_context_out->current->modify_over->y = -1;
1586 draw_context_out->current->modify_middle = g_new(ItemInfo,1);
1587 draw_context_out->current->modify_middle->x = -1;
1588 draw_context_out->current->modify_middle->y = -1;
1589 draw_context_out->current->modify_under = g_new(ItemInfo,1);
1590 draw_context_out->current->modify_under->x = -1;
1591 draw_context_out->current->modify_under->y = -1;
1592 draw_context_out->current->status = LTTV_STATE_UNNAMED;
1593
1594 /* Finally, update the drawing context of the pid_in. */
1595
1596 DrawContext *draw_context_in = hashed_process_data_in->draw_context;
1597 //draw_context_in->current->modify_over->x = x;
1598 draw_context_in->current->modify_over->y = y_in;
1599 draw_context_in->current->modify_under->y = y_in+(height/2)+2;
1600 draw_context_in->drawable = control_flow_data->drawing->pixmap;
1601 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
1602 widget = control_flow_data->drawing->drawing_area;
1603 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
1604
1605 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
1606 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
1607
1608 /*if(process_in->state->s == LTTV_STATE_RUN)
1609 {
1610 draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1611 gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1612 PropertiesBG prop_bg;
1613 prop_bg.color = g_new(GdkColor,1);
1614
1615 prop_bg.color->red = 0xffff;
1616 prop_bg.color->green = 0xffff;
1617 prop_bg.color->blue = 0xffff;
1618
1619 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1620 g_free(prop_bg.color);
1621 gdk_gc_unref(draw_context_in->gc);
1622 }*/
1623
1624 draw_context_in->gc = widget->style->black_gc;
1625
1626 GdkColor colorfg_in = { 0, 0x0000, 0xffff, 0x0000 };
1627 GdkColor colorbg_in = { 0, 0x0000, 0x0000, 0x0000 };
1628 PropertiesText prop_text_in;
1629 prop_text_in.foreground = &colorfg_in;
1630 prop_text_in.background = &colorbg_in;
1631 prop_text_in.size = 6;
1632 prop_text_in.position = OVER;
1633
1634 /* foreground of text : status of the process */
1635 if(process_in->state->s == LTTV_STATE_UNNAMED)
1636 {
1637 prop_text_in.foreground->red = 0xffff;
1638 prop_text_in.foreground->green = 0xffff;
1639 prop_text_in.foreground->blue = 0xffff;
1640 }
1641 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1642 {
1643 prop_text_in.foreground->red = 0x0fff;
1644 prop_text_in.foreground->green = 0xffff;
1645 prop_text_in.foreground->blue = 0xfff0;
1646 }
1647 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1648 {
1649 prop_text_in.foreground->red = 0xffff;
1650 prop_text_in.foreground->green = 0xffff;
1651 prop_text_in.foreground->blue = 0x0000;
1652 }
1653 else if(process_in->state->s == LTTV_STATE_EXIT)
1654 {
1655 prop_text_in.foreground->red = 0xffff;
1656 prop_text_in.foreground->green = 0x0000;
1657 prop_text_in.foreground->blue = 0xffff;
1658 }
1659 else if(process_in->state->s == LTTV_STATE_WAIT)
1660 {
1661 prop_text_in.foreground->red = 0xffff;
1662 prop_text_in.foreground->green = 0x0000;
1663 prop_text_in.foreground->blue = 0x0000;
1664 }
1665 else if(process_in->state->s == LTTV_STATE_RUN)
1666 {
1667 prop_text_in.foreground->red = 0x0000;
1668 prop_text_in.foreground->green = 0xffff;
1669 prop_text_in.foreground->blue = 0x0000;
1670 }
1671 else
1672 {
1673 prop_text_in.foreground->red = 0xffff;
1674 prop_text_in.foreground->green = 0xffff;
1675 prop_text_in.foreground->blue = 0xffff;
1676 }
1677
1678
1679 /* Print status of the process : U, WF, WC, E, W, R */
1680 if(process_in->state->s == LTTV_STATE_UNNAMED)
1681 prop_text_in.text = "U";
1682 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1683 prop_text_in.text = "WF";
1684 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1685 prop_text_in.text = "WC";
1686 else if(process_in->state->s == LTTV_STATE_EXIT)
1687 prop_text_in.text = "E";
1688 else if(process_in->state->s == LTTV_STATE_WAIT)
1689 prop_text_in.text = "W";
1690 else if(process_in->state->s == LTTV_STATE_RUN)
1691 prop_text_in.text = "R";
1692 else
1693 prop_text_in.text = "U";
1694
1695 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1696
1697
1698 if(process_in->state->s == LTTV_STATE_RUN)
1699 {
1700 gchar tmp[255];
1701 prop_text_in.foreground = &colorfg_in;
1702 prop_text_in.background = &colorbg_in;
1703 prop_text_in.foreground->red = 0xffff;
1704 prop_text_in.foreground->green = 0xffff;
1705 prop_text_in.foreground->blue = 0xffff;
1706 prop_text_in.size = 6;
1707 prop_text_in.position = UNDER;
1708
1709 prop_text_in.text = g_new(gchar, 260);
1710 strcpy(prop_text_in.text, "CPU ");
1711 snprintf(tmp, 255, "%u", tfc->index);
1712 strcat(prop_text_in.text, tmp);
1713
1714 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1715 g_free(prop_text_in.text);
1716 }
1717
1718
1719 draw_context_in->current->middle->y = y_in+height/2;
1720 draw_context_in->current->over->y = y_in;
1721 draw_context_in->current->under->y = y_in+height;
1722 draw_context_in->current->status = process_in->state->s;
1723
1724 /* for pid_in : remove previous, Prev = current, new current (default) */
1725 g_free(draw_context_in->previous->modify_under);
1726 g_free(draw_context_in->previous->modify_middle);
1727 g_free(draw_context_in->previous->modify_over);
1728 g_free(draw_context_in->previous->under);
1729 g_free(draw_context_in->previous->middle);
1730 g_free(draw_context_in->previous->over);
1731 g_free(draw_context_in->previous);
1732
1733 draw_context_in->previous = draw_context_in->current;
1734
1735 draw_context_in->current = g_new(DrawInfo,1);
1736 draw_context_in->current->over = g_new(ItemInfo,1);
1737 draw_context_in->current->over->x = -1;
1738 draw_context_in->current->over->y = -1;
1739 draw_context_in->current->middle = g_new(ItemInfo,1);
1740 draw_context_in->current->middle->x = -1;
1741 draw_context_in->current->middle->y = -1;
1742 draw_context_in->current->under = g_new(ItemInfo,1);
1743 draw_context_in->current->under->x = -1;
1744 draw_context_in->current->under->y = -1;
1745 draw_context_in->current->modify_over = g_new(ItemInfo,1);
1746 draw_context_in->current->modify_over->x = -1;
1747 draw_context_in->current->modify_over->y = -1;
1748 draw_context_in->current->modify_middle = g_new(ItemInfo,1);
1749 draw_context_in->current->modify_middle->x = -1;
1750 draw_context_in->current->modify_middle->y = -1;
1751 draw_context_in->current->modify_under = g_new(ItemInfo,1);
1752 draw_context_in->current->modify_under->x = -1;
1753 draw_context_in->current->modify_under->y = -1;
1754 draw_context_in->current->status = LTTV_STATE_UNNAMED;
1755
1756 }
1757
1758 return 0;
1759#endif //0
1760}
1761
1762
1763
1764
1765gint update_time_window_hook(void *hook_data, void *call_data)
1766{
1767 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
1768 Drawing_t *drawing = control_flow_data->drawing;
1769
1770 const TimeWindowNotifyData *time_window_nofify_data =
1771 ((const TimeWindowNotifyData *)call_data);
1772
1773 TimeWindow *old_time_window =
1774 time_window_nofify_data->old_time_window;
1775 TimeWindow *new_time_window =
1776 time_window_nofify_data->new_time_window;
1777
1778 /* Update the ruler */
1779 drawing_update_ruler(control_flow_data->drawing,
1780 new_time_window);
1781
1782
1783 /* Two cases : zoom in/out or scrolling */
1784
1785 /* In order to make sure we can reuse the old drawing, the scale must
1786 * be the same and the new time interval being partly located in the
1787 * currently shown time interval. (reuse is only for scrolling)
1788 */
1789
1790 g_info("Old time window HOOK : %u, %u to %u, %u",
1791 old_time_window->start_time.tv_sec,
1792 old_time_window->start_time.tv_nsec,
1793 old_time_window->time_width.tv_sec,
1794 old_time_window->time_width.tv_nsec);
1795
1796 g_info("New time window HOOK : %u, %u to %u, %u",
1797 new_time_window->start_time.tv_sec,
1798 new_time_window->start_time.tv_nsec,
1799 new_time_window->time_width.tv_sec,
1800 new_time_window->time_width.tv_nsec);
1801
1802 if( new_time_window->time_width.tv_sec == old_time_window->time_width.tv_sec
1803 && new_time_window->time_width.tv_nsec == old_time_window->time_width.tv_nsec)
1804 {
1805 /* Same scale (scrolling) */
1806 g_info("scrolling");
1807 LttTime *ns = &new_time_window->start_time;
1808 LttTime *os = &old_time_window->start_time;
1809 LttTime old_end = ltt_time_add(old_time_window->start_time,
1810 old_time_window->time_width);
1811 LttTime new_end = ltt_time_add(new_time_window->start_time,
1812 new_time_window->time_width);
1813 //if(ns<os+w<ns+w)
1814 //if(ns<os+w && os+w<ns+w)
1815 //if(ns<old_end && os<ns)
1816 if(ltt_time_compare(*ns, old_end) == -1
1817 && ltt_time_compare(*os, *ns) == -1)
1818 {
1819 g_info("scrolling near right");
1820 /* Scroll right, keep right part of the screen */
1821 guint x = 0;
1822 guint width = control_flow_data->drawing->width;
1823 convert_time_to_pixels(
1824 *os,
1825 old_end,
1826 *ns,
1827 width,
1828 &x);
1829
1830 /* Copy old data to new location */
1831 gdk_draw_drawable (control_flow_data->drawing->pixmap,
1832 control_flow_data->drawing->drawing_area->style->black_gc,
1833 control_flow_data->drawing->pixmap,
1834 x, 0,
1835 0, 0,
1836 control_flow_data->drawing->width-x+SAFETY, -1);
1837
1838 if(drawing->damage_begin == drawing->damage_end)
1839 drawing->damage_begin = control_flow_data->drawing->width-x;
1840 else
1841 drawing->damage_begin = 0;
1842
1843 drawing->damage_end = control_flow_data->drawing->width;
1844
1845 /* Clear the data request background, but not SAFETY */
1846 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
1847 //control_flow_data->drawing->drawing_area->style->black_gc,
1848 control_flow_data->drawing->drawing_area->style->black_gc,
1849 TRUE,
1850 drawing->damage_begin+SAFETY, 0,
1851 drawing->damage_end - drawing->damage_begin, // do not overlap
1852 control_flow_data->drawing->height);
1853
1854 gtk_widget_queue_draw_area (drawing->drawing_area,
1855 0,0,
1856 control_flow_data->drawing->width,
1857 control_flow_data->drawing->height);
1858
1859 /* Get new data for the rest. */
1860 drawing_data_request(control_flow_data->drawing,
1861 &control_flow_data->drawing->pixmap,
1862 drawing->damage_begin, 0,
1863 drawing->damage_end - drawing->damage_begin,
1864 control_flow_data->drawing->height);
1865 } else {
1866 //if(ns<os<ns+w)
1867 //if(ns<os && os<ns+w)
1868 //if(ns<os && os<new_end)
1869 if(ltt_time_compare(*ns,*os) == -1
1870 && ltt_time_compare(*os,new_end) == -1)
1871 {
1872 g_info("scrolling near left");
1873 /* Scroll left, keep left part of the screen */
1874 guint x = 0;
1875 guint width = control_flow_data->drawing->width;
1876 convert_time_to_pixels(
1877 *ns,
1878 new_end,
1879 *os,
1880 width,
1881 &x);
1882
1883
1884 /* Copy old data to new location */
1885 gdk_draw_drawable (control_flow_data->drawing->pixmap,
1886 control_flow_data->drawing->drawing_area->style->black_gc,
1887 control_flow_data->drawing->pixmap,
1888 0, 0,
1889 x, 0,
1890 -1, -1);
1891
1892 if(drawing->damage_begin == drawing->damage_end)
1893 drawing->damage_end = x;
1894 else
1895 drawing->damage_end =
1896 control_flow_data->drawing->width;
1897
1898 drawing->damage_begin = 0;
1899
1900 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
1901 control_flow_data->drawing->drawing_area->style->black_gc,
1902 TRUE,
1903 drawing->damage_begin, 0,
1904 drawing->damage_end - drawing->damage_begin, // do not overlap
1905 control_flow_data->drawing->height);
1906
1907 gtk_widget_queue_draw_area (drawing->drawing_area,
1908 0,0,
1909 control_flow_data->drawing->width,
1910 control_flow_data->drawing->height);
1911
1912
1913 /* Get new data for the rest. */
1914 drawing_data_request(control_flow_data->drawing,
1915 &control_flow_data->drawing->pixmap,
1916 drawing->damage_begin, 0,
1917 drawing->damage_end - drawing->damage_begin,
1918 control_flow_data->drawing->height);
1919
1920 } else {
1921 if(ltt_time_compare(*ns,*os) == 0)
1922 {
1923 g_info("not scrolling");
1924 } else {
1925 g_info("scrolling far");
1926 /* Cannot reuse any part of the screen : far jump */
1927
1928
1929 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
1930 control_flow_data->drawing->drawing_area->style->black_gc,
1931 TRUE,
1932 0, 0,
1933 control_flow_data->drawing->width+SAFETY, // do not overlap
1934 control_flow_data->drawing->height);
1935
1936 gtk_widget_queue_draw_area (drawing->drawing_area,
1937 0,0,
1938 control_flow_data->drawing->width,
1939 control_flow_data->drawing->height);
1940
1941 drawing->damage_begin = 0;
1942 drawing->damage_end = control_flow_data->drawing->width;
1943
1944 drawing_data_request(control_flow_data->drawing,
1945 &control_flow_data->drawing->pixmap,
1946 0, 0,
1947 control_flow_data->drawing->width,
1948 control_flow_data->drawing->height);
1949
1950 }
1951 }
1952 }
1953 } else {
1954 /* Different scale (zoom) */
1955 g_info("zoom");
1956
1957 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
1958 control_flow_data->drawing->drawing_area->style->black_gc,
1959 TRUE,
1960 0, 0,
1961 control_flow_data->drawing->width+SAFETY, // do not overlap
1962 control_flow_data->drawing->height);
1963
1964 gtk_widget_queue_draw_area (drawing->drawing_area,
1965 0,0,
1966 control_flow_data->drawing->width,
1967 control_flow_data->drawing->height);
1968
1969 drawing->damage_begin = 0;
1970 drawing->damage_end = control_flow_data->drawing->width;
1971
1972 drawing_data_request(control_flow_data->drawing,
1973 &control_flow_data->drawing->pixmap,
1974 0, 0,
1975 control_flow_data->drawing->width,
1976 control_flow_data->drawing->height);
1977 }
1978
1979
1980
1981 return 0;
1982}
1983
1984gint traceset_notify(void *hook_data, void *call_data)
1985{
1986 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
1987 Drawing_t *drawing = control_flow_data->drawing;
1988 GtkWidget *widget = drawing->drawing_area;
1989
1990
1991 drawing_clear(control_flow_data->drawing);
1992 processlist_clear(control_flow_data->process_list);
1993 redraw_notify(control_flow_data, NULL);
1994
1995 request_background_data(control_flow_data);
1996#if 0
1997 drawing->damage_begin = 0;
1998 drawing->damage_end = drawing->width;
1999 if(drawing->damage_begin < drawing->damage_end)
2000 {
2001 drawing_data_request(drawing,
2002 &drawing->pixmap,
2003 drawing->damage_begin,
2004 0,
2005 drawing->damage_end-drawing->damage_begin,
2006 drawing->height);
2007 }
2008
2009 gtk_widget_queue_draw_area(drawing->drawing_area,
2010 0,0,
2011 drawing->width,
2012 drawing->height);
2013#endif //0
2014
2015 return FALSE;
2016}
2017
2018gint redraw_notify(void *hook_data, void *call_data)
2019{
2020 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2021 Drawing_t *drawing = control_flow_data->drawing;
2022 GtkWidget *widget = drawing->drawing_area;
2023
2024 drawing->damage_begin = 0;
2025 drawing->damage_end = drawing->width;
2026
2027
2028 // Clear the image
2029 gdk_draw_rectangle (drawing->pixmap,
2030 widget->style->black_gc,
2031 TRUE,
2032 0, 0,
2033 drawing->width+SAFETY,
2034 drawing->height);
2035
2036
2037 if(drawing->damage_begin < drawing->damage_end)
2038 {
2039 drawing_data_request(drawing,
2040 &drawing->pixmap,
2041 drawing->damage_begin,
2042 0,
2043 drawing->damage_end-drawing->damage_begin,
2044 drawing->height);
2045 }
2046
2047 gtk_widget_queue_draw_area(drawing->drawing_area,
2048 0,0,
2049 drawing->width,
2050 drawing->height);
2051
2052 return FALSE;
2053
2054}
2055
2056
2057gint continue_notify(void *hook_data, void *call_data)
2058{
2059 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2060 Drawing_t *drawing = control_flow_data->drawing;
2061 GtkWidget *widget = drawing->drawing_area;
2062
2063 //g_assert(widget->allocation.width == drawing->damage_end);
2064
2065 if(drawing->damage_begin < drawing->damage_end)
2066 {
2067 drawing_data_request(drawing,
2068 &drawing->pixmap,
2069 drawing->damage_begin,
2070 0,
2071 drawing->damage_end-drawing->damage_begin,
2072 drawing->height);
2073 }
2074
2075 return FALSE;
2076}
2077
2078
2079gint update_current_time_hook(void *hook_data, void *call_data)
2080{
2081 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
2082 Drawing_t *drawing = control_flow_data->drawing;
2083
2084 LttTime current_time = *((LttTime*)call_data);
2085
2086 TimeWindow time_window =
2087 lttvwindow_get_time_window(control_flow_data->tab);
2088
2089 LttTime time_begin = time_window.start_time;
2090 LttTime width = time_window.time_width;
2091 LttTime half_width = ltt_time_div(width,2.0);
2092 LttTime time_end = ltt_time_add(time_begin, width);
2093
2094 LttvTracesetContext * tsc =
2095 lttvwindow_get_traceset_context(control_flow_data->tab);
2096
2097 LttTime trace_start = tsc->time_span.start_time;
2098 LttTime trace_end = tsc->time_span.end_time;
2099
2100 g_info("New current time HOOK : %u, %u", current_time.tv_sec,
2101 current_time.tv_nsec);
2102
2103
2104
2105 /* If current time is inside time interval, just move the highlight
2106 * bar */
2107
2108 /* Else, we have to change the time interval. We have to tell it
2109 * to the main window. */
2110 /* The time interval change will take care of placing the current
2111 * time at the center of the visible area, or nearest possible if we are
2112 * at one end of the trace. */
2113
2114
2115 if(ltt_time_compare(current_time, time_begin) == -1)
2116 {
2117 TimeWindow new_time_window;
2118
2119 if(ltt_time_compare(current_time,
2120 ltt_time_add(trace_start,half_width)) == -1)
2121 time_begin = trace_start;
2122 else
2123 time_begin = ltt_time_sub(current_time,half_width);
2124
2125 new_time_window.start_time = time_begin;
2126 new_time_window.time_width = width;
2127
2128 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
2129 }
2130 else if(ltt_time_compare(current_time, time_end) == 1)
2131 {
2132 TimeWindow new_time_window;
2133
2134 if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) == 1)
2135 time_begin = ltt_time_sub(trace_end,width);
2136 else
2137 time_begin = ltt_time_sub(current_time,half_width);
2138
2139 new_time_window.start_time = time_begin;
2140 new_time_window.time_width = width;
2141
2142 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
2143
2144 }
2145 //gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
2146 gtk_widget_queue_draw_area(drawing->drawing_area,
2147 0,0,
2148 drawing->width,
2149 drawing->height);
2150
2151 return 0;
2152}
2153
2154typedef struct _ClosureData {
2155 EventsRequest *events_request;
2156 LttvTracesetState *tss;
2157 LttTime end_time;
2158} ClosureData;
2159
2160
2161/* find_process
2162 * Input : A trace and a PID.
2163 *
2164 * - For each CPU of the trace
2165 * - Search in trace states by PID and CPU key
2166 * - If no ProcessState found, return NULL.
2167 */
2168static LttvProcessState *find_process(LttvTraceState *tstate, guint pid)
2169{
2170 guint cpu_num = ltt_trace_per_cpu_tracefile_number(tstate->parent.t);
2171 GQuark cpu_name;
2172 guint i;
2173
2174 LttvProcessState *real_state = NULL;
2175
2176 for(i=0;i<cpu_num;i++) {
2177 cpu_name = ((LttvTracefileState*)tstate->parent.tracefiles[i])->cpu_name;
2178 LttvProcessState *state = lttv_state_find_process_from_trace(tstate,
2179 cpu_name,
2180 pid);
2181 if(state != NULL) {
2182 real_state = state;
2183 break;
2184 }
2185 }
2186 return real_state;
2187}
2188
2189
2190void draw_closure(gpointer key, gpointer value, gpointer user_data)
2191{
2192 ProcessInfo *process_info = (ProcessInfo*)key;
2193 HashedProcessData *hashed_process_data = (HashedProcessData*)value;
2194 ClosureData *closure_data = (ClosureData*)user_data;
2195
2196 EventsRequest *events_request = closure_data->events_request;
2197 ControlFlowData *control_flow_data = events_request->viewer_data;
2198 Drawing_t *drawing = control_flow_data->drawing;
2199
2200 LttvTracesetState *tss = closure_data->tss;
2201 LttvTracesetContext *tsc = (LttvTracesetContext*)closure_data->tss;
2202
2203 LttTime evtime = closure_data->end_time;
2204 TimeWindow time_window =
2205 lttvwindow_get_time_window(control_flow_data->tab);
2206
2207 LttTime end_time = ltt_time_add(time_window.start_time,
2208 time_window.time_width);
2209
2210 if(ltt_time_compare(evtime, time_window.start_time) == -1
2211 || ltt_time_compare(evtime, end_time) == 1)
2212 return;
2213
2214 guint width = drawing->width;
2215
2216 {
2217 /* For the process */
2218 /* First, check if the current process is in the state computation
2219 * process list. If it is there, that means we must add it right now and
2220 * draw items from the beginning of the read for it. If it is not
2221 * present, it's a new process and it was not present : it will
2222 * be added after the state update. */
2223 g_assert(lttv_traceset_number(tsc->ts) > 0);
2224
2225 LttvTraceState *trace_state =
2226 (LttvTraceState*)tsc->traces[process_info->trace_num];
2227
2228 LttvProcessState *process;
2229 process = find_process(trace_state, process_info->pid);
2230
2231 if(process != NULL) {
2232
2233 /* Only draw for processes that are currently in the trace states */
2234
2235 guint y = 0, height = 0, pl_height = 0;
2236 ProcessList *process_list =
2237 guicontrolflow_get_process_list(control_flow_data);
2238 LttTime birth = process_info->birth;
2239
2240 /* Should be alike when background info is ready */
2241 if(control_flow_data->background_info_waiting==0)
2242 g_assert(ltt_time_compare(process->creation_time,
2243 process_info->birth) == 0);
2244 const gchar *name = g_quark_to_string(process->name);
2245
2246 /* process HAS to be present */
2247 g_assert(processlist_get_process_pixels(process_list,
2248 process_info->pid,
2249 &birth,
2250 process_info->trace_num,
2251 &y,
2252 &height,
2253 &hashed_process_data) != 1);
2254
2255 /* Now, the process is in the state hash and our own process hash.
2256 * We definitely can draw the items related to the ending state.
2257 */
2258
2259 /* Check if the x position is unset. In can have been left unset by
2260 * a draw closure from a after chunk hook. This should never happen,
2261 * because it must be set by before chunk hook to the damage_begin
2262 * value.
2263 */
2264 g_assert(hashed_process_data->x != -1);
2265 {
2266 guint x;
2267 DrawContext draw_context;
2268
2269 convert_time_to_pixels(
2270 time_window.start_time,
2271 end_time,
2272 evtime,
2273 width,
2274 &x);
2275
2276 /* Now create the drawing context that will be used to draw
2277 * items related to the last state. */
2278 draw_context.drawable = drawing->pixmap;
2279 draw_context.gc = drawing->gc;
2280 draw_context.pango_layout = drawing->pango_layout;
2281 draw_context.drawinfo.start.x = hashed_process_data->x;
2282 draw_context.drawinfo.end.x = x;
2283
2284 draw_context.drawinfo.y.over = y;
2285 draw_context.drawinfo.y.middle = y+(height/4);
2286 draw_context.drawinfo.y.under = y+(height/2)+2;
2287
2288 draw_context.drawinfo.start.offset.over = 0;
2289 draw_context.drawinfo.start.offset.middle = 0;
2290 draw_context.drawinfo.start.offset.under = 0;
2291 draw_context.drawinfo.end.offset.over = 0;
2292 draw_context.drawinfo.end.offset.middle = 0;
2293 draw_context.drawinfo.end.offset.under = 0;
2294
2295 {
2296 /* Draw the line */
2297 PropertiesLine prop_line = prepare_line(process);
2298 draw_line((void*)&prop_line, (void*)&draw_context);
2299
2300 }
2301
2302 /* special case LTTV_STATE_WAIT : CPU is unknown. */
2303
2304 /* become the last x position */
2305 hashed_process_data->x = x;
2306 }
2307 }
2308 }
2309 return;
2310}
2311
2312int before_chunk(void *hook_data, void *call_data)
2313{
2314 EventsRequest *events_request = (EventsRequest*)hook_data;
2315 LttvTracesetState *tss = LTTV_TRACESET_STATE(call_data);
2316
2317 drawing_chunk_begin(events_request, tss);
2318
2319 return 0;
2320}
2321
2322int before_request(void *hook_data, void *call_data)
2323{
2324 EventsRequest *events_request = (EventsRequest*)hook_data;
2325 LttvTracesetState *tss = LTTV_TRACESET_STATE(call_data);
2326
2327 drawing_data_request_begin(events_request, tss);
2328
2329 return 0;
2330}
2331
2332
2333/*
2334 * after request is necessary in addition of after chunk in order to draw
2335 * lines until the end of the screen. after chunk just draws lines until
2336 * the last event.
2337 *
2338 * for each process
2339 * draw closing line
2340 * expose
2341 */
2342int after_request(void *hook_data, void *call_data)
2343{
2344 EventsRequest *events_request = (EventsRequest*)hook_data;
2345 ControlFlowData *control_flow_data = events_request->viewer_data;
2346 LttvTracesetState *tss = LTTV_TRACESET_STATE(call_data);
2347 LttvTracesetContext *tsc = LTTV_TRACESET_CONTEXT(call_data);
2348
2349 ProcessList *process_list =
2350 guicontrolflow_get_process_list(control_flow_data);
2351 LttTime end_time = events_request->end_time;
2352
2353 ClosureData closure_data;
2354 closure_data.events_request = (EventsRequest*)hook_data;
2355 closure_data.tss = tss;
2356 closure_data.end_time = end_time;
2357
2358 /* Draw last items */
2359 g_hash_table_foreach(process_list->process_hash, draw_closure,
2360 (void*)&closure_data);
2361
2362 /* Request expose */
2363 drawing_request_expose(events_request, tss, end_time);
2364 return 0;
2365}
2366
2367/*
2368 * for each process
2369 * draw closing line
2370 * expose
2371 */
2372int after_chunk(void *hook_data, void *call_data)
2373{
2374 EventsRequest *events_request = (EventsRequest*)hook_data;
2375 ControlFlowData *control_flow_data = events_request->viewer_data;
2376 LttvTracesetState *tss = LTTV_TRACESET_STATE(call_data);
2377 LttvTracesetContext *tsc = LTTV_TRACESET_CONTEXT(call_data);
2378 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
2379 LttTime end_time;
2380
2381 ProcessList *process_list =
2382 guicontrolflow_get_process_list(control_flow_data);
2383
2384 if(tfc != NULL)
2385 end_time = LTT_TIME_MIN(tfc->timestamp, events_request->end_time);
2386 else /* end of traceset, or position now out of request : end */
2387 end_time = events_request->end_time;
2388
2389 ClosureData closure_data;
2390 closure_data.events_request = (EventsRequest*)hook_data;
2391 closure_data.tss = tss;
2392 closure_data.end_time = end_time;
2393
2394 /* Draw last items */
2395 g_hash_table_foreach(process_list->process_hash, draw_closure,
2396 (void*)&closure_data);
2397
2398 /* Request expose */
2399 drawing_request_expose(events_request, tss, end_time);
2400
2401 return 0;
2402}
2403
This page took 0.029914 seconds and 4 git commands to generate.