fix colors
[lttv.git] / ltt / branches / poly / lttv / modules / gui / controlflow / eventhooks.c
CommitLineData
ce0214a6 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
f0d936c0 20/*****************************************************************************
21 * Hooks to be called by the main window *
22 *****************************************************************************/
23
f0d936c0 24
b9a010a2 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 *
e92eabaf 28 * Two hooks are used for drawing : before_schedchange and after_schedchange hooks. The
29 * before_schedchange is called before the state update that occurs with an event and
30 * the after_schedchange hook is called after this state update.
b9a010a2 31 *
e92eabaf 32 * The before_schedchange hooks fulfill the task of drawing the visible objects that
33 * corresponds to the data accumulated by the after_schedchange hook.
b9a010a2 34 *
e92eabaf 35 * The after_schedchange hook accumulates the data that need to be shown on the screen
36 * (items) into a queue. Then, the next before_schedchange hook will draw what that
b9a010a2 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
e92eabaf 40 * corresponding to it is over, which happens to be at the next before_schedchange
b9a010a2 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
cf6cb7e0 49//#define PANGO_ENABLE_BACKEND
558aa013 50#include <gtk/gtk.h>
51#include <gdk/gdk.h>
5f16133f 52#include <glib.h>
80a52ff8 53#include <assert.h>
50439712 54#include <string.h>
319e9d81 55#include <stdio.h>
5f16133f 56
cf6cb7e0 57//#include <pango/pango.h>
58
80a52ff8 59#include <ltt/event.h>
4ba42155 60#include <ltt/time.h>
50439712 61#include <ltt/type.h>
80a52ff8 62
2a2fa4f0 63#include <lttv/lttv.h>
558aa013 64#include <lttv/hook.h>
80a52ff8 65#include <lttv/state.h>
2d262115 66#include <lttvwindow/lttvwindow.h>
6395d57c 67#include <lttvwindow/lttvwindowtraces.h>
80a52ff8 68
f0d936c0 69
a117e3f7 70#include "eventhooks.h"
71#include "cfv.h"
72#include "processlist.h"
73#include "drawing.h"
74#include "cfv-private.h"
5f16133f 75
80a52ff8 76
1a31868c 77#define MAX_PATH_LEN 256
78
f0d936c0 79
b9a010a2 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
6395d57c 137/* Action to do when background computation completed.
138 *
e800cf84 139 * Wait for all the awaited computations to be over.
6395d57c 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;
b9a010a2 146 LttvTracesetContext *tsc =
147 lttvwindow_get_traceset_context(control_flow_data->tab);
6395d57c 148
e800cf84 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.");
6395d57c 153
e800cf84 154 drawing_clear(control_flow_data->drawing);
155 processlist_clear(control_flow_data->process_list);
156 redraw_notify(control_flow_data, NULL);
b9a010a2 157 }
6395d57c 158
159 return 0;
160}
161
162
163/* Request background computation. Verify if it is in progress or ready first.
e800cf84 164 * Only for each trace in the tab's traceset.
6395d57c 165 */
166void request_background_data(ControlFlowData *control_flow_data)
167{
e800cf84 168 LttvTracesetContext * tsc =
169 lttvwindow_get_traceset_context(control_flow_data->tab);
170 gint num_traces = lttv_traceset_number(tsc->ts);
6395d57c 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);
e800cf84 178 control_flow_data->background_info_waiting = 0;
6395d57c 179
180 for(i=0;i<num_traces;i++) {
e800cf84 181 trace = lttv_traceset_get(tsc->ts, i);
6395d57c 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);
e800cf84 199 control_flow_data->background_info_waiting++;
6395d57c 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);
e800cf84 207 control_flow_data->background_info_waiting++;
6395d57c 208 }
4368b993 209 } else {
210 /* Data ready. Be its nature, this viewer doesn't need to have
211 * its data ready hook called htere, because a background
212 * request is always linked with a redraw.
213 */
6395d57c 214 }
4368b993 215
6395d57c 216 }
217
218 lttv_hooks_destroy(background_ready_hook);
219}
220
221
222
223
f0d936c0 224/**
225 * Event Viewer's constructor hook
226 *
227 * This constructor is given as a parameter to the menuitem and toolbar button
228 * registration. It creates the list.
ca0f8a8e 229 * @param tab A pointer to the parent tab.
f0d936c0 230 * @return The widget created.
231 */
232GtkWidget *
d47b33d2 233h_guicontrolflow(Tab *tab)
f0d936c0 234{
d47b33d2 235 g_info("h_guicontrolflow, %p", tab);
68997a22 236 ControlFlowData *control_flow_data = guicontrolflow() ;
a56a1ba4 237
ca0f8a8e 238 control_flow_data->tab = tab;
a56a1ba4 239
2a2fa4f0 240 //g_debug("time width2 : %u",time_window->time_width);
a56a1ba4 241 // Unreg done in the GuiControlFlow_Destructor
6395d57c 242 lttvwindow_register_traceset_notify(tab,
243 traceset_notify,
244 control_flow_data);
245
ca0f8a8e 246 lttvwindow_register_time_window_notify(tab,
224446ce 247 update_time_window_hook,
248 control_flow_data);
ca0f8a8e 249 lttvwindow_register_current_time_notify(tab,
224446ce 250 update_current_time_hook,
251 control_flow_data);
ca0f8a8e 252 lttvwindow_register_redraw_notify(tab,
253 redraw_notify,
254 control_flow_data);
255 lttvwindow_register_continue_notify(tab,
256 continue_notify,
257 control_flow_data);
6395d57c 258 request_background_data(control_flow_data);
259
ca0f8a8e 260
68997a22 261 return guicontrolflow_get_widget(control_flow_data) ;
a56a1ba4 262
f0d936c0 263}
264
3cff8cc1 265int event_selected_hook(void *hook_data, void *call_data)
f0d936c0 266{
68997a22 267 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
14963be0 268 guint *event_number = (guint*) call_data;
f0d936c0 269
2a2fa4f0 270 g_debug("DEBUG : event selected by main window : %u", *event_number);
a56a1ba4 271
f0d936c0 272}
273
c8bba5fa 274
e92eabaf 275static __inline PropertiesLine prepare_status_line(LttvProcessState *process)
c8bba5fa 276{
277 PropertiesLine prop_line;
278 prop_line.line_width = 2;
279 prop_line.style = GDK_LINE_SOLID;
e800cf84 280 prop_line.y = MIDDLE;
281 //GdkColormap *colormap = gdk_colormap_get_system();
c8bba5fa 282
23093869 283 g_debug("prepare_status_line for state : %s",
284 g_quark_to_string(process->state->s));
c8bba5fa 285
286 /* color of line : status of the process */
287 if(process->state->s == LTTV_STATE_UNNAMED)
e800cf84 288 prop_line.color = drawing_colors[COL_WHITE];
c8bba5fa 289 else if(process->state->s == LTTV_STATE_WAIT_FORK)
e800cf84 290 prop_line.color = drawing_colors[COL_WAIT_FORK];
c8bba5fa 291 else if(process->state->s == LTTV_STATE_WAIT_CPU)
e800cf84 292 prop_line.color = drawing_colors[COL_WAIT_CPU];
dbd243b1 293 else if(process->state->s == LTTV_STATE_EXIT)
294 prop_line.color = drawing_colors[COL_EXIT];
0828099d 295 else if(process->state->s == LTTV_STATE_ZOMBIE)
296 prop_line.color = drawing_colors[COL_ZOMBIE];
c8bba5fa 297 else if(process->state->s == LTTV_STATE_WAIT)
e800cf84 298 prop_line.color = drawing_colors[COL_WAIT];
c8bba5fa 299 else if(process->state->s == LTTV_STATE_RUN)
e800cf84 300 prop_line.color = drawing_colors[COL_RUN];
c8bba5fa 301 else
23093869 302 prop_line.color = drawing_colors[COL_WHITE];
e800cf84 303
304 //gdk_colormap_alloc_color(colormap,
305 // prop_line.color,
306 // FALSE,
307 // TRUE);
c8bba5fa 308
309 return prop_line;
310
311}
312
313
314
e92eabaf 315/* before_schedchange_hook
b9a010a2 316 *
f0d936c0 317 * This function basically draw lines and icons. Two types of lines are drawn :
318 * one small (3 pixels?) representing the state of the process and the second
319 * type is thicker (10 pixels?) representing on which CPU a process is running
320 * (and this only in running state).
321 *
322 * Extremums of the lines :
323 * x_min : time of the last event context for this process kept in memory.
324 * x_max : time of the current event.
325 * y : middle of the process in the process list. The process is found in the
326 * list, therefore is it's position in pixels.
327 *
328 * The choice of lines'color is defined by the context of the last event for this
329 * process.
330 */
b9a010a2 331
332
e92eabaf 333int before_schedchange_hook(void *hook_data, void *call_data)
f0d936c0 334{
b9a010a2 335 EventsRequest *events_request = (EventsRequest*)hook_data;
336 ControlFlowData *control_flow_data = events_request->viewer_data;
c8bba5fa 337 Drawing_t *drawing = control_flow_data->drawing;
b9a010a2 338
339 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
340
341 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
342 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
343
344 LttEvent *e;
345 e = tfc->e;
346
347 LttTime evtime = ltt_event_time(e);
348 TimeWindow time_window =
349 lttvwindow_get_time_window(control_flow_data->tab);
350
351 LttTime end_time = ltt_time_add(time_window.start_time,
352 time_window.time_width);
353
354 if(ltt_time_compare(evtime, time_window.start_time) == -1
355 || ltt_time_compare(evtime, end_time) == 1)
356 return;
357
c8bba5fa 358 guint width = drawing->width;
b9a010a2 359
10a1069a 360 /* we are in a schedchange, before the state update. We must draw the
361 * items corresponding to the state before it changes : now is the right
362 * time to do it.
363 */
b9a010a2 364
10a1069a 365 guint pid_out;
366 guint pid_in;
367 {
368 LttField *f = ltt_event_field(e);
369 LttField *element;
370 element = ltt_field_member(f,0);
371 pid_out = ltt_event_get_long_unsigned(e,element);
372 element = ltt_field_member(f,1);
373 pid_in = ltt_event_get_long_unsigned(e,element);
374 g_debug("out : %u in : %u", pid_out, pid_in);
375 }
376
377 {
378 /* For the pid_out */
379 /* First, check if the current process is in the state computation
380 * process list. If it is there, that means we must add it right now and
381 * draw items from the beginning of the read for it. If it is not
382 * present, it's a new process and it was not present : it will
383 * be added after the state update. */
384 LttvProcessState *process;
385 process = lttv_state_find_process(tfs, pid_out);
b9a010a2 386
10a1069a 387 if(process != NULL) {
388 /* Well, the process_out existed : we must get it in the process hash
389 * or add it, and draw its items.
390 */
391 /* Add process to process list (if not present) */
392 guint y = 0, height = 0, pl_height = 0;
393 HashedProcessData *hashed_process_data = NULL;
394 ProcessList *process_list =
395 guicontrolflow_get_process_list(control_flow_data);
396 LttTime birth = process->creation_time;
397 const gchar *name = g_quark_to_string(process->name);
b9a010a2 398
10a1069a 399 if(processlist_get_process_pixels(process_list,
400 pid_out,
401 process->last_cpu,
402 &birth,
403 tfc->t_context->index,
404 &y,
405 &height,
406 &hashed_process_data) == 1)
407 {
408 g_assert(pid_out == 0 || pid_out != process->ppid);
409 /* Process not present */
410 processlist_add(process_list,
411 pid_out,
412 process->last_cpu,
413 process->ppid,
414 &birth,
415 tfc->t_context->index,
416 name,
417 &pl_height,
418 &hashed_process_data);
419 processlist_get_process_pixels(process_list,
e800cf84 420 pid_out,
a95bc95a 421 process->last_cpu,
e800cf84 422 &birth,
423 tfc->t_context->index,
424 &y,
425 &height,
10a1069a 426 &hashed_process_data);
427 drawing_insert_square( drawing, y, height);
428 }
429
430 /* Now, the process is in the state hash and our own process hash.
431 * We definitely can draw the items related to the ending state.
432 */
e800cf84 433
10a1069a 434 /* Check if the x position is unset. In can have been left unset by
435 * a draw closure from a after chunk hook. This should never happen,
436 * because it must be set by before chunk hook to the damage_begin
437 * value.
438 */
439 g_assert(hashed_process_data->x.middle != -1);
440 {
441 guint x;
442 DrawContext draw_context;
443
444 convert_time_to_pixels(
445 time_window.start_time,
446 end_time,
447 evtime,
448 width,
449 &x);
450
451 /* Now create the drawing context that will be used to draw
452 * items related to the last state. */
453 draw_context.drawable = drawing->pixmap;
454 draw_context.gc = drawing->gc;
455 draw_context.pango_layout = drawing->pango_layout;
456 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
457 draw_context.drawinfo.end.x = x;
458
459 draw_context.drawinfo.y.over = y+1;
460 draw_context.drawinfo.y.middle = y+(height/2);
461 draw_context.drawinfo.y.under = y+height;
462
463 draw_context.drawinfo.start.offset.over = 0;
464 draw_context.drawinfo.start.offset.middle = 0;
465 draw_context.drawinfo.start.offset.under = 0;
466 draw_context.drawinfo.end.offset.over = 0;
467 draw_context.drawinfo.end.offset.middle = 0;
468 draw_context.drawinfo.end.offset.under = 0;
469
e800cf84 470 {
10a1069a 471 /* Draw the line */
472 PropertiesLine prop_line = prepare_status_line(process);
473 draw_line((void*)&prop_line, (void*)&draw_context);
474
e800cf84 475 }
10a1069a 476 /* become the last x position */
477 hashed_process_data->x.middle = x;
e800cf84 478 }
479 }
10a1069a 480 }
e800cf84 481
10a1069a 482 {
483 /* For the pid_in */
484 /* First, check if the current process is in the state computation
485 * process list. If it is there, that means we must add it right now and
486 * draw items from the beginning of the read for it. If it is not
487 * present, it's a new process and it was not present : it will
488 * be added after the state update. */
489 LttvProcessState *process;
490 process = lttv_state_find_process(tfs, pid_in);
491
492 if(process != NULL) {
493 /* Well, the process_out existed : we must get it in the process hash
494 * or add it, and draw its items.
495 */
496 /* Add process to process list (if not present) */
497 guint y = 0, height = 0, pl_height = 0;
498 HashedProcessData *hashed_process_data = NULL;
499 ProcessList *process_list =
500 guicontrolflow_get_process_list(control_flow_data);
501 LttTime birth = process->creation_time;
502 const gchar *name = g_quark_to_string(process->name);
e800cf84 503
10a1069a 504 if(processlist_get_process_pixels(process_list,
505 pid_in,
506 process->last_cpu,
507 &birth,
508 tfc->t_context->index,
509 &y,
510 &height,
511 &hashed_process_data) == 1)
512 {
513 g_assert(pid_in == 0 || pid_in != process->ppid);
514 /* Process not present */
515 processlist_add(process_list,
516 pid_in,
517 process->last_cpu,
518 process->ppid,
519 &birth,
520 tfc->t_context->index,
521 name,
522 &pl_height,
523 &hashed_process_data);
524 processlist_get_process_pixels(process_list,
e800cf84 525 pid_in,
a95bc95a 526 process->last_cpu,
b9a010a2 527 &birth,
528 tfc->t_context->index,
c8bba5fa 529 &y,
b9a010a2 530 &height,
10a1069a 531 &hashed_process_data);
532 drawing_insert_square( drawing, y, height);
533 }
534
535 /* Now, the process is in the state hash and our own process hash.
536 * We definitely can draw the items related to the ending state.
537 */
b9a010a2 538
10a1069a 539 /* Check if the x position is unset. In can have been left unset by
540 * a draw closure from a after chunk hook. This should never happen,
541 * because it must be set by before chunk hook to the damage_begin
542 * value.
543 */
544 g_assert(hashed_process_data->x.middle != -1);
545 {
546 guint x;
547 DrawContext draw_context;
548
549 convert_time_to_pixels(
550 time_window.start_time,
551 end_time,
552 evtime,
553 width,
554 &x);
555
556 /* Now create the drawing context that will be used to draw
557 * items related to the last state. */
558 draw_context.drawable = drawing->pixmap;
559 draw_context.gc = drawing->gc;
560 draw_context.pango_layout = drawing->pango_layout;
561 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
562 draw_context.drawinfo.end.x = x;
563
564 draw_context.drawinfo.y.over = y+1;
565 draw_context.drawinfo.y.middle = y+(height/2);
566 draw_context.drawinfo.y.under = y+height;
567
568 draw_context.drawinfo.start.offset.over = 0;
569 draw_context.drawinfo.start.offset.middle = 0;
570 draw_context.drawinfo.start.offset.under = 0;
571 draw_context.drawinfo.end.offset.over = 0;
572 draw_context.drawinfo.end.offset.middle = 0;
573 draw_context.drawinfo.end.offset.under = 0;
574
c8bba5fa 575 {
10a1069a 576 /* Draw the line */
577 PropertiesLine prop_line = prepare_status_line(process);
578 draw_line((void*)&prop_line, (void*)&draw_context);
c8bba5fa 579 }
10a1069a 580
581
582 /* become the last x position */
583 hashed_process_data->x.middle = x;
c8bba5fa 584 }
b9a010a2 585 }
586 }
b9a010a2 587 return 0;
588
589
b9a010a2 590#if 0
ca0f8a8e 591 EventsRequest *events_request = (EventsRequest*)hook_data;
592 ControlFlowData *control_flow_data =
593 (ControlFlowData*)events_request->viewer_data;
594 Tab *tab = control_flow_data->tab;
e9a9c513 595
a56a1ba4 596 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
e9a9c513 597
598 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1aff52a2 599 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
a56a1ba4 600
e9a9c513 601 LttEvent *e;
e9a9c513 602 e = tfc->e;
603
9444deae 604 LttTime evtime = ltt_event_time(e);
ca0f8a8e 605 TimeWindow time_window =
606 lttvwindow_get_time_window(tab);
9444deae 607
ca0f8a8e 608 LttTime end_time = ltt_time_add(time_window.start_time,
609 time_window.time_width);
9444deae 610 //if(time < time_beg || time > time_end) return;
ca0f8a8e 611 if(ltt_time_compare(evtime, time_window.start_time) == -1
9444deae 612 || ltt_time_compare(evtime, end_time) == 1)
613 return;
614
a56a1ba4 615 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0)
616 {
2a2fa4f0 617 g_debug("schedchange!");
a56a1ba4 618
619 /* Add process to process list (if not present) and get drawing "y" from
620 * process position */
621 guint pid_out, pid_in;
622 LttvProcessState *process_out, *process_in;
623 LttTime birth;
624 guint y_in = 0, y_out = 0, height = 0, pl_height = 0;
625
626 ProcessList *process_list =
ca0f8a8e 627 guicontrolflow_get_process_list(control_flow_data);
a56a1ba4 628
629
630 LttField *f = ltt_event_field(e);
631 LttField *element;
632 element = ltt_field_member(f,0);
633 pid_out = ltt_event_get_long_unsigned(e,element);
634 element = ltt_field_member(f,1);
635 pid_in = ltt_event_get_long_unsigned(e,element);
2a2fa4f0 636 g_debug("out : %u in : %u", pid_out, pid_in);
a56a1ba4 637
638
639 /* Find process pid_out in the list... */
87658614 640 process_out = lttv_state_find_process(tfs, pid_out);
1aff52a2 641 if(process_out == NULL) return 0;
2a2fa4f0 642 g_debug("out : %s",g_quark_to_string(process_out->state->s));
1aff52a2 643
a56a1ba4 644 birth = process_out->creation_time;
51705146 645 const gchar *name = g_quark_to_string(process_out->name);
14963be0 646 HashedProcessData *hashed_process_data_out = NULL;
a56a1ba4 647
648 if(processlist_get_process_pixels(process_list,
649 pid_out,
650 &birth,
d0cd7f09 651 tfc->t_context->index,
a56a1ba4 652 &y_out,
653 &height,
14963be0 654 &hashed_process_data_out) == 1)
a56a1ba4 655 {
51705146 656 /* Process not present */
657 processlist_add(process_list,
658 pid_out,
659 &birth,
660 tfc->t_context->index,
661 name,
662 &pl_height,
663 &hashed_process_data_out);
664 g_assert(processlist_get_process_pixels(process_list,
665 pid_out,
666 &birth,
667 tfc->t_context->index,
668 &y_out,
669 &height,
670 &hashed_process_data_out)==0);
671 drawing_insert_square( control_flow_data->drawing, y_out, height);
a56a1ba4 672 }
51705146 673 //g_free(name);
a56a1ba4 674
675 /* Find process pid_in in the list... */
87658614 676 process_in = lttv_state_find_process(tfs, pid_in);
1aff52a2 677 if(process_in == NULL) return 0;
2a2fa4f0 678 g_debug("in : %s",g_quark_to_string(process_in->state->s));
a56a1ba4 679
680 birth = process_in->creation_time;
51705146 681 name = g_quark_to_string(process_in->name);
14963be0 682 HashedProcessData *hashed_process_data_in = NULL;
a56a1ba4 683
684 if(processlist_get_process_pixels(process_list,
685 pid_in,
686 &birth,
d0cd7f09 687 tfc->t_context->index,
a56a1ba4 688 &y_in,
689 &height,
14963be0 690 &hashed_process_data_in) == 1)
a56a1ba4 691 {
51705146 692 /* Process not present */
a56a1ba4 693 processlist_add(process_list,
694 pid_in,
695 &birth,
d0cd7f09 696 tfc->t_context->index,
a56a1ba4 697 name,
698 &pl_height,
14963be0 699 &hashed_process_data_in);
a56a1ba4 700 processlist_get_process_pixels(process_list,
701 pid_in,
702 &birth,
d0cd7f09 703 tfc->t_context->index,
a56a1ba4 704 &y_in,
705 &height,
14963be0 706 &hashed_process_data_in);
a56a1ba4 707
ca0f8a8e 708 drawing_insert_square( control_flow_data->drawing, y_in, height);
a56a1ba4 709 }
51705146 710 //g_free(name);
a56a1ba4 711
712
713 /* Find pixels corresponding to time of the event. If the time does
714 * not fit in the window, show a warning, not supposed to happend. */
715 guint x = 0;
51705146 716 guint width = control_flow_data->drawing->width;
a56a1ba4 717
718 LttTime time = ltt_event_time(e);
719
ca0f8a8e 720 LttTime window_end = ltt_time_add(time_window.time_width,
721 time_window.start_time);
a56a1ba4 722
723
724 convert_time_to_pixels(
ca0f8a8e 725 time_window.start_time,
a56a1ba4 726 window_end,
727 time,
728 width,
729 &x);
9444deae 730 //assert(x <= width);
51705146 731 //
a56a1ba4 732 /* draw what represents the event for outgoing process. */
733
14963be0 734 DrawContext *draw_context_out = hashed_process_data_out->draw_context;
68997a22 735 draw_context_out->current->modify_over->x = x;
319e9d81 736 draw_context_out->current->modify_under->x = x;
68997a22 737 draw_context_out->current->modify_over->y = y_out;
319e9d81 738 draw_context_out->current->modify_under->y = y_out+(height/2)+2;
501d5405 739 draw_context_out->drawable = control_flow_data->drawing->pixmap;
740 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
741 GtkWidget *widget = control_flow_data->drawing->drawing_area;
a56a1ba4 742 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
d0cd7f09 743 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
744 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
a56a1ba4 745 //draw_context_out->gc = widget->style->black_gc;
746
747 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
501d5405 748 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
a56a1ba4 749
d0cd7f09 750 /* Draw the line/background of the out process */
751 if(draw_context_out->previous->middle->x == -1)
752 {
ca0f8a8e 753 draw_context_out->previous->over->x =
754 control_flow_data->drawing->damage_begin;
755 draw_context_out->previous->middle->x =
756 control_flow_data->drawing->damage_begin;
757 draw_context_out->previous->under->x =
758 control_flow_data->drawing->damage_begin;
759
760 g_debug("out middle x_beg : %u",control_flow_data->drawing->damage_begin);
d0cd7f09 761 }
762
763 draw_context_out->current->middle->x = x;
764 draw_context_out->current->over->x = x;
765 draw_context_out->current->under->x = x;
766 draw_context_out->current->middle->y = y_out + height/2;
767 draw_context_out->current->over->y = y_out;
768 draw_context_out->current->under->y = y_out + height;
769 draw_context_out->previous->middle->y = y_out + height/2;
770 draw_context_out->previous->over->y = y_out;
771 draw_context_out->previous->under->y = y_out + height;
772
773 draw_context_out->drawable = control_flow_data->drawing->pixmap;
774 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
775
776 if(process_out->state->s == LTTV_STATE_RUN)
777 {
51705146 778 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
779 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
780 draw_context_out->gc = control_flow_data->drawing->gc;
d0cd7f09 781
782 PropertiesBG prop_bg;
783 prop_bg.color = g_new(GdkColor,1);
784
785 switch(tfc->index) {
786 case 0:
787 prop_bg.color->red = 0x1515;
788 prop_bg.color->green = 0x1515;
789 prop_bg.color->blue = 0x8c8c;
790 break;
791 case 1:
792 prop_bg.color->red = 0x4e4e;
793 prop_bg.color->green = 0xa9a9;
794 prop_bg.color->blue = 0xa4a4;
795 break;
796 case 2:
797 prop_bg.color->red = 0x7a7a;
798 prop_bg.color->green = 0x4a4a;
799 prop_bg.color->blue = 0x8b8b;
800 break;
801 case 3:
802 prop_bg.color->red = 0x8080;
803 prop_bg.color->green = 0x7777;
804 prop_bg.color->blue = 0x4747;
805 break;
806 default:
807 prop_bg.color->red = 0xe7e7;
808 prop_bg.color->green = 0xe7e7;
809 prop_bg.color->blue = 0xe7e7;
810 }
811
2a2fa4f0 812 g_debug("calling from draw_event");
d0cd7f09 813 draw_bg((void*)&prop_bg, (void*)draw_context_out);
814 g_free(prop_bg.color);
51705146 815 //gdk_gc_unref(draw_context_out->gc);
d0cd7f09 816 }
817
818 draw_context_out->gc = widget->style->black_gc;
819
a56a1ba4 820 GdkColor colorfg_out = { 0, 0xffff, 0x0000, 0x0000 };
2df6f2bd 821 GdkColor colorbg_out = { 0, 0x0000, 0x0000, 0x0000 };
a56a1ba4 822 PropertiesText prop_text_out;
823 prop_text_out.foreground = &colorfg_out;
824 prop_text_out.background = &colorbg_out;
cfe526b1 825 prop_text_out.size = 6;
a56a1ba4 826 prop_text_out.position = OVER;
827
cfe526b1 828 /* color of text : status of the process */
829 if(process_out->state->s == LTTV_STATE_UNNAMED)
830 {
831 prop_text_out.foreground->red = 0xffff;
832 prop_text_out.foreground->green = 0xffff;
833 prop_text_out.foreground->blue = 0xffff;
834 }
835 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
836 {
837 prop_text_out.foreground->red = 0x0fff;
d52cfc84 838 prop_text_out.foreground->green = 0xffff;
839 prop_text_out.foreground->blue = 0xfff0;
cfe526b1 840 }
841 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
842 {
2df6f2bd 843 prop_text_out.foreground->red = 0xffff;
844 prop_text_out.foreground->green = 0xffff;
cfe526b1 845 prop_text_out.foreground->blue = 0x0000;
846 }
0828099d 847 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
cfe526b1 848 {
849 prop_text_out.foreground->red = 0xffff;
850 prop_text_out.foreground->green = 0x0000;
851 prop_text_out.foreground->blue = 0xffff;
852 }
853 else if(process_out->state->s == LTTV_STATE_WAIT)
854 {
855 prop_text_out.foreground->red = 0xffff;
856 prop_text_out.foreground->green = 0x0000;
857 prop_text_out.foreground->blue = 0x0000;
858 }
859 else if(process_out->state->s == LTTV_STATE_RUN)
860 {
861 prop_text_out.foreground->red = 0x0000;
862 prop_text_out.foreground->green = 0xffff;
863 prop_text_out.foreground->blue = 0x0000;
864 }
865 else
866 {
867 prop_text_out.foreground->red = 0xffff;
868 prop_text_out.foreground->green = 0xffff;
869 prop_text_out.foreground->blue = 0xffff;
870 }
871
d52cfc84 872
a56a1ba4 873 /* Print status of the process : U, WF, WC, E, W, R */
874 if(process_out->state->s == LTTV_STATE_UNNAMED)
cfe526b1 875 prop_text_out.text = "U->";
a56a1ba4 876 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
cfe526b1 877 prop_text_out.text = "WF->";
a56a1ba4 878 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
cfe526b1 879 prop_text_out.text = "WC->";
0828099d 880 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
cfe526b1 881 prop_text_out.text = "E->";
a56a1ba4 882 else if(process_out->state->s == LTTV_STATE_WAIT)
cfe526b1 883 prop_text_out.text = "W->";
a56a1ba4 884 else if(process_out->state->s == LTTV_STATE_RUN)
cfe526b1 885 prop_text_out.text = "R->";
a56a1ba4 886 else
68997a22 887 prop_text_out.text = "U";
a56a1ba4 888
889 draw_text((void*)&prop_text_out, (void*)draw_context_out);
d0cd7f09 890 //gdk_gc_unref(draw_context_out->gc);
a56a1ba4 891
51705146 892 //draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
893 //gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
894 draw_context_out->gc = control_flow_data->drawing->gc;
a56a1ba4 895
896 PropertiesLine prop_line_out;
897 prop_line_out.color = g_new(GdkColor,1);
cfe526b1 898 prop_line_out.line_width = 2;
a56a1ba4 899 prop_line_out.style = GDK_LINE_SOLID;
900 prop_line_out.position = MIDDLE;
d52cfc84 901
2a2fa4f0 902 g_debug("out state : %s", g_quark_to_string(process_out->state->s));
a56a1ba4 903
904 /* color of line : status of the process */
905 if(process_out->state->s == LTTV_STATE_UNNAMED)
906 {
cfe526b1 907 prop_line_out.color->red = 0xffff;
908 prop_line_out.color->green = 0xffff;
909 prop_line_out.color->blue = 0xffff;
a56a1ba4 910 }
911 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
912 {
913 prop_line_out.color->red = 0x0fff;
d52cfc84 914 prop_line_out.color->green = 0xffff;
915 prop_line_out.color->blue = 0xfff0;
a56a1ba4 916 }
917 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
918 {
2df6f2bd 919 prop_line_out.color->red = 0xffff;
920 prop_line_out.color->green = 0xffff;
a56a1ba4 921 prop_line_out.color->blue = 0x0000;
922 }
0828099d 923 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
a56a1ba4 924 {
925 prop_line_out.color->red = 0xffff;
926 prop_line_out.color->green = 0x0000;
927 prop_line_out.color->blue = 0xffff;
928 }
929 else if(process_out->state->s == LTTV_STATE_WAIT)
930 {
931 prop_line_out.color->red = 0xffff;
932 prop_line_out.color->green = 0x0000;
933 prop_line_out.color->blue = 0x0000;
934 }
935 else if(process_out->state->s == LTTV_STATE_RUN)
936 {
937 prop_line_out.color->red = 0x0000;
938 prop_line_out.color->green = 0xffff;
939 prop_line_out.color->blue = 0x0000;
940 }
941 else
942 {
cfe526b1 943 prop_line_out.color->red = 0xffff;
944 prop_line_out.color->green = 0xffff;
945 prop_line_out.color->blue = 0xffff;
a56a1ba4 946 }
947
948 draw_line((void*)&prop_line_out, (void*)draw_context_out);
949 g_free(prop_line_out.color);
51705146 950 //gdk_gc_unref(draw_context_out->gc);
a56a1ba4 951 /* Note : finishing line will have to be added when trace read over. */
952
953 /* Finally, update the drawing context of the pid_in. */
954
14963be0 955 DrawContext *draw_context_in = hashed_process_data_in->draw_context;
68997a22 956 draw_context_in->current->modify_over->x = x;
319e9d81 957 draw_context_in->current->modify_under->x = x;
68997a22 958 draw_context_in->current->modify_over->y = y_in;
319e9d81 959 draw_context_in->current->modify_under->y = y_in+(height/2)+2;
501d5405 960 draw_context_in->drawable = control_flow_data->drawing->pixmap;
961 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
962 widget = control_flow_data->drawing->drawing_area;
a56a1ba4 963 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
964 //draw_context_in->gc = widget->style->black_gc;
d0cd7f09 965 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
966 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
a56a1ba4 967
968 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
501d5405 969 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
d0cd7f09 970
971 /* Draw the line/bg of the in process */
972 if(draw_context_in->previous->middle->x == -1)
973 {
ca0f8a8e 974 draw_context_in->previous->over->x =
975 control_flow_data->drawing->damage_begin;
976 draw_context_in->previous->middle->x =
977 control_flow_data->drawing->damage_begin;
978 draw_context_in->previous->under->x =
979 control_flow_data->drawing->damage_begin;
980
981 g_debug("in middle x_beg : %u",control_flow_data->drawing->damage_begin);
982
d0cd7f09 983 }
984
985 draw_context_in->current->middle->x = x;
986 draw_context_in->current->over->x = x;
987 draw_context_in->current->under->x = x;
988 draw_context_in->current->middle->y = y_in + height/2;
989 draw_context_in->current->over->y = y_in;
990 draw_context_in->current->under->y = y_in + height;
991 draw_context_in->previous->middle->y = y_in + height/2;
992 draw_context_in->previous->over->y = y_in;
993 draw_context_in->previous->under->y = y_in + height;
a56a1ba4 994
d0cd7f09 995 draw_context_in->drawable = control_flow_data->drawing->pixmap;
996 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
997
998
999 if(process_in->state->s == LTTV_STATE_RUN)
1000 {
51705146 1001 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1002 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1003 draw_context_in->gc = control_flow_data->drawing->gc;
d0cd7f09 1004
1005 PropertiesBG prop_bg;
1006 prop_bg.color = g_new(GdkColor,1);
1007
1008 switch(tfc->index) {
1009 case 0:
1010 prop_bg.color->red = 0x1515;
1011 prop_bg.color->green = 0x1515;
1012 prop_bg.color->blue = 0x8c8c;
1013 break;
1014 case 1:
1015 prop_bg.color->red = 0x4e4e;
1016 prop_bg.color->green = 0xa9a9;
1017 prop_bg.color->blue = 0xa4a4;
1018 break;
1019 case 2:
1020 prop_bg.color->red = 0x7a7a;
1021 prop_bg.color->green = 0x4a4a;
1022 prop_bg.color->blue = 0x8b8b;
1023 break;
1024 case 3:
1025 prop_bg.color->red = 0x8080;
1026 prop_bg.color->green = 0x7777;
1027 prop_bg.color->blue = 0x4747;
1028 break;
1029 default:
1030 prop_bg.color->red = 0xe7e7;
1031 prop_bg.color->green = 0xe7e7;
1032 prop_bg.color->blue = 0xe7e7;
1033 }
1034
1035
1036 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1037 g_free(prop_bg.color);
51705146 1038 //gdk_gc_unref(draw_context_in->gc);
d0cd7f09 1039 }
1040
1041 draw_context_in->gc = widget->style->black_gc;
1042
a56a1ba4 1043 GdkColor colorfg_in = { 0, 0x0000, 0xffff, 0x0000 };
2df6f2bd 1044 GdkColor colorbg_in = { 0, 0x0000, 0x0000, 0x0000 };
a56a1ba4 1045 PropertiesText prop_text_in;
1046 prop_text_in.foreground = &colorfg_in;
1047 prop_text_in.background = &colorbg_in;
cfe526b1 1048 prop_text_in.size = 6;
a56a1ba4 1049 prop_text_in.position = OVER;
1050
2a2fa4f0 1051 g_debug("in state : %s", g_quark_to_string(process_in->state->s));
cfe526b1 1052 /* foreground of text : status of the process */
1053 if(process_in->state->s == LTTV_STATE_UNNAMED)
1054 {
1055 prop_text_in.foreground->red = 0xffff;
1056 prop_text_in.foreground->green = 0xffff;
1057 prop_text_in.foreground->blue = 0xffff;
1058 }
1059 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1060 {
1061 prop_text_in.foreground->red = 0x0fff;
d52cfc84 1062 prop_text_in.foreground->green = 0xffff;
1063 prop_text_in.foreground->blue = 0xfff0;
cfe526b1 1064 }
1065 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1066 {
2df6f2bd 1067 prop_text_in.foreground->red = 0xffff;
1068 prop_text_in.foreground->green = 0xffff;
cfe526b1 1069 prop_text_in.foreground->blue = 0x0000;
1070 }
0828099d 1071 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
cfe526b1 1072 {
1073 prop_text_in.foreground->red = 0xffff;
1074 prop_text_in.foreground->green = 0x0000;
1075 prop_text_in.foreground->blue = 0xffff;
1076 }
1077 else if(process_in->state->s == LTTV_STATE_WAIT)
1078 {
1079 prop_text_in.foreground->red = 0xffff;
1080 prop_text_in.foreground->green = 0x0000;
1081 prop_text_in.foreground->blue = 0x0000;
1082 }
1083 else if(process_in->state->s == LTTV_STATE_RUN)
1084 {
1085 prop_text_in.foreground->red = 0x0000;
1086 prop_text_in.foreground->green = 0xffff;
1087 prop_text_in.foreground->blue = 0x0000;
1088 }
1089 else
1090 {
1091 prop_text_in.foreground->red = 0xffff;
1092 prop_text_in.foreground->green = 0xffff;
1093 prop_text_in.foreground->blue = 0xffff;
1094 }
1095
1096
1097
a56a1ba4 1098 /* Print status of the process : U, WF, WC, E, W, R */
1099 if(process_in->state->s == LTTV_STATE_UNNAMED)
cfe526b1 1100 prop_text_in.text = "U->";
a56a1ba4 1101 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
cfe526b1 1102 prop_text_in.text = "WF->";
a56a1ba4 1103 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
cfe526b1 1104 prop_text_in.text = "WC->";
0828099d 1105 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
cfe526b1 1106 prop_text_in.text = "E->";
a56a1ba4 1107 else if(process_in->state->s == LTTV_STATE_WAIT)
cfe526b1 1108 prop_text_in.text = "W->";
a56a1ba4 1109 else if(process_in->state->s == LTTV_STATE_RUN)
cfe526b1 1110 prop_text_in.text = "R->";
a56a1ba4 1111 else
68997a22 1112 prop_text_in.text = "U";
a56a1ba4 1113
1114 draw_text((void*)&prop_text_in, (void*)draw_context_in);
d0cd7f09 1115 //gdk_gc_unref(draw_context_in->gc);
1116
51705146 1117 //draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1118 //gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1119 draw_context_in->gc = control_flow_data->drawing->gc;
d0cd7f09 1120
a56a1ba4 1121 PropertiesLine prop_line_in;
1122 prop_line_in.color = g_new(GdkColor,1);
cfe526b1 1123 prop_line_in.line_width = 2;
a56a1ba4 1124 prop_line_in.style = GDK_LINE_SOLID;
1125 prop_line_in.position = MIDDLE;
1126
1127 /* color of line : status of the process */
1128 if(process_in->state->s == LTTV_STATE_UNNAMED)
1129 {
cfe526b1 1130 prop_line_in.color->red = 0xffff;
1131 prop_line_in.color->green = 0xffff;
1132 prop_line_in.color->blue = 0xffff;
a56a1ba4 1133 }
1134 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1135 {
1136 prop_line_in.color->red = 0x0fff;
d52cfc84 1137 prop_line_in.color->green = 0xffff;
1138 prop_line_in.color->blue = 0xfff0;
a56a1ba4 1139 }
1140 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1141 {
2df6f2bd 1142 prop_line_in.color->red = 0xffff;
1143 prop_line_in.color->green = 0xffff;
a56a1ba4 1144 prop_line_in.color->blue = 0x0000;
1145 }
0828099d 1146 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
a56a1ba4 1147 {
1148 prop_line_in.color->red = 0xffff;
1149 prop_line_in.color->green = 0x0000;
1150 prop_line_in.color->blue = 0xffff;
1151 }
1152 else if(process_in->state->s == LTTV_STATE_WAIT)
1153 {
1154 prop_line_in.color->red = 0xffff;
1155 prop_line_in.color->green = 0x0000;
1156 prop_line_in.color->blue = 0x0000;
1157 }
1158 else if(process_in->state->s == LTTV_STATE_RUN)
1159 {
1160 prop_line_in.color->red = 0x0000;
1161 prop_line_in.color->green = 0xffff;
1162 prop_line_in.color->blue = 0x0000;
1163 }
1164 else
1165 {
cfe526b1 1166 prop_line_in.color->red = 0xffff;
1167 prop_line_in.color->green = 0xffff;
1168 prop_line_in.color->blue = 0xffff;
a56a1ba4 1169 }
1170
1171 draw_line((void*)&prop_line_in, (void*)draw_context_in);
1172 g_free(prop_line_in.color);
51705146 1173 //gdk_gc_unref(draw_context_in->gc);
a56a1ba4 1174 }
1175
1176 return 0;
b9a010a2 1177#endif //0
1178
1179
a56a1ba4 1180
51705146 1181 /* Text dump */
80a52ff8 1182#ifdef DONTSHOW
a56a1ba4 1183 GString *string = g_string_new("");;
1184 gboolean field_names = TRUE, state = TRUE;
80a52ff8 1185
e9a9c513 1186 lttv_event_to_string(e, tfc->tf, string, TRUE, field_names, tfs);
1187 g_string_append_printf(string,"\n");
1188
1189 if(state) {
1190 g_string_append_printf(string, " %s",
1191 g_quark_to_string(tfs->process->state->s));
1192 }
1193
1194 g_info("%s",string->str);
1195
a56a1ba4 1196 g_string_free(string, TRUE);
1197
1198 /* End of text dump */
80a52ff8 1199#endif //DONTSHOW
50439712 1200
f0d936c0 1201}
1202
e92eabaf 1203/* after_schedchange_hook
b9a010a2 1204 *
1205 * The draw after hook is called by the reading API to have a
1206 * particular event drawn on the screen.
1207 * @param hook_data ControlFlowData structure of the viewer.
1208 * @param call_data Event context.
1209 *
1210 * This function adds items to be drawn in a queue for each process.
1211 *
1212 */
e92eabaf 1213int after_schedchange_hook(void *hook_data, void *call_data)
f0d936c0 1214{
ca0f8a8e 1215 EventsRequest *events_request = (EventsRequest*)hook_data;
1216 ControlFlowData *control_flow_data = events_request->viewer_data;
50439712 1217
a56a1ba4 1218 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
50439712 1219
1220 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1aff52a2 1221 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
50439712 1222
b9a010a2 1223 LttEvent *e;
1224 e = tfc->e;
1225
1226 LttTime evtime = ltt_event_time(e);
1227 TimeWindow time_window =
1228 lttvwindow_get_time_window(control_flow_data->tab);
1229
1230 LttTime end_time = ltt_time_add(time_window.start_time,
1231 time_window.time_width);
1232
1233 if(ltt_time_compare(evtime, time_window.start_time) == -1
1234 || ltt_time_compare(evtime, end_time) == 1)
1235 return;
1236
1237 guint width = control_flow_data->drawing->width;
1238
10a1069a 1239 /* Add process to process list (if not present) */
1240 LttvProcessState *process_out, *process_in;
1241 LttTime birth;
1242 guint y_in = 0, y_out = 0, height = 0, pl_height = 0;
1243 HashedProcessData *hashed_process_data_in = NULL;
b9a010a2 1244
10a1069a 1245 ProcessList *process_list =
1246 guicontrolflow_get_process_list(control_flow_data);
1247
1248 guint pid_in;
1249 {
1250 guint pid_out;
1251 LttField *f = ltt_event_field(e);
1252 LttField *element;
1253 element = ltt_field_member(f,0);
1254 pid_out = ltt_event_get_long_unsigned(e,element);
1255 element = ltt_field_member(f,1);
1256 pid_in = ltt_event_get_long_unsigned(e,element);
1257 g_debug("out : %u in : %u", pid_out, pid_in);
1258 }
b9a010a2 1259
1260
10a1069a 1261 /* Find process pid_in in the list... */
1262 process_in = lttv_state_find_process(tfs, pid_in);
1263 /* It should exist, because we are after the state update. */
1264 g_assert(process_in != NULL);
b9a010a2 1265
10a1069a 1266 birth = process_in->creation_time;
1267 const gchar *name = g_quark_to_string(process_in->name);
b9a010a2 1268
10a1069a 1269 if(processlist_get_process_pixels(process_list,
1270 pid_in,
1271 process_in->last_cpu,
1272 &birth,
1273 tfc->t_context->index,
1274 &y_in,
1275 &height,
1276 &hashed_process_data_in) == 1)
1277 {
1278 g_assert(pid_in == 0 || pid_in != process_in->ppid);
1279 /* Process not present */
1280 processlist_add(process_list,
1281 pid_in,
1282 process_in->last_cpu,
1283 process_in->ppid,
1284 &birth,
1285 tfc->t_context->index,
1286 name,
1287 &pl_height,
1288 &hashed_process_data_in);
1289 processlist_get_process_pixels(process_list,
b9a010a2 1290 pid_in,
a95bc95a 1291 process_in->last_cpu,
b9a010a2 1292 &birth,
1293 tfc->t_context->index,
10a1069a 1294 &y_in,
1295 &height,
b9a010a2 1296 &hashed_process_data_in);
10a1069a 1297 drawing_insert_square( control_flow_data->drawing, y_in, height);
b9a010a2 1298 }
10a1069a 1299
1300 convert_time_to_pixels(
1301 time_window.start_time,
1302 end_time,
1303 evtime,
1304 width,
1305 &hashed_process_data_in->x.middle);
b9a010a2 1306 return 0;
1307
1308
1309
1310#if 0
1311 EventsRequest *events_request = (EventsRequest*)hook_data;
1312 ControlFlowData *control_flow_data = events_request->viewer_data;
1313
1314 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1315
1316 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1317 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
1318
a56a1ba4 1319
50439712 1320 LttEvent *e;
1321 e = tfc->e;
1322
9444deae 1323 LttTime evtime = ltt_event_time(e);
ca0f8a8e 1324 TimeWindow time_window =
1325 lttvwindow_get_time_window(control_flow_data->tab);
9444deae 1326
ca0f8a8e 1327 LttTime end_time = ltt_time_add(time_window.start_time,
1328 time_window.time_width);
9444deae 1329 //if(time < time_beg || time > time_end) return;
ca0f8a8e 1330 if(ltt_time_compare(evtime, time_window.start_time) == -1
9444deae 1331 || ltt_time_compare(evtime, end_time) == 1)
1332 return;
1333
1334
a56a1ba4 1335 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0)
1336 {
2a2fa4f0 1337 g_debug("schedchange!");
a56a1ba4 1338
1339 /* Add process to process list (if not present) and get drawing "y" from
1340 * process position */
1341 guint pid_out, pid_in;
1342 LttvProcessState *process_out, *process_in;
1343 LttTime birth;
1344 guint y_in = 0, y_out = 0, height = 0, pl_height = 0;
1345
1346 ProcessList *process_list =
ca0f8a8e 1347 guicontrolflow_get_process_list(control_flow_data);
a56a1ba4 1348
1349
1350 LttField *f = ltt_event_field(e);
1351 LttField *element;
1352 element = ltt_field_member(f,0);
1353 pid_out = ltt_event_get_long_unsigned(e,element);
1354 element = ltt_field_member(f,1);
1355 pid_in = ltt_event_get_long_unsigned(e,element);
2a2fa4f0 1356 //g_debug("out : %u in : %u", pid_out, pid_in);
a56a1ba4 1357
1358
1359 /* Find process pid_out in the list... */
2a2fa4f0 1360 process_out = lttv_state_find_process(tfs, pid_out);
1aff52a2 1361 if(process_out == NULL) return 0;
2a2fa4f0 1362 //g_debug("out : %s",g_quark_to_string(process_out->state->s));
a56a1ba4 1363
1364 birth = process_out->creation_time;
1365 gchar *name = strdup(g_quark_to_string(process_out->name));
14963be0 1366 HashedProcessData *hashed_process_data_out = NULL;
a56a1ba4 1367
1368 if(processlist_get_process_pixels(process_list,
1369 pid_out,
1370 &birth,
d0cd7f09 1371 tfc->t_context->index,
a56a1ba4 1372 &y_out,
1373 &height,
14963be0 1374 &hashed_process_data_out) == 1)
a56a1ba4 1375 {
51705146 1376 /* Process not present */
1377 processlist_add(process_list,
1378 pid_out,
1379 &birth,
1380 tfc->t_context->index,
1381 name,
1382 &pl_height,
1383 &hashed_process_data_out);
1384 processlist_get_process_pixels(process_list,
1385 pid_out,
1386 &birth,
1387 tfc->t_context->index,
1388 &y_out,
1389 &height,
1390 &hashed_process_data_out);
1391 drawing_insert_square( control_flow_data->drawing, y_out, height);
a56a1ba4 1392 }
1393
1394 g_free(name);
1395
1396 /* Find process pid_in in the list... */
2a2fa4f0 1397 process_in = lttv_state_find_process(tfs, pid_in);
1aff52a2 1398 if(process_in == NULL) return 0;
2a2fa4f0 1399 //g_debug("in : %s",g_quark_to_string(process_in->state->s));
a56a1ba4 1400
1401 birth = process_in->creation_time;
1402 name = strdup(g_quark_to_string(process_in->name));
14963be0 1403 HashedProcessData *hashed_process_data_in = NULL;
a56a1ba4 1404
1405 if(processlist_get_process_pixels(process_list,
1406 pid_in,
1407 &birth,
d0cd7f09 1408 tfc->t_context->index,
a56a1ba4 1409 &y_in,
1410 &height,
14963be0 1411 &hashed_process_data_in) == 1)
a56a1ba4 1412 {
1413 /* Process not present */
1414 processlist_add(process_list,
1415 pid_in,
1416 &birth,
d0cd7f09 1417 tfc->t_context->index,
a56a1ba4 1418 name,
1419 &pl_height,
14963be0 1420 &hashed_process_data_in);
a56a1ba4 1421 processlist_get_process_pixels(process_list,
1422 pid_in,
1423 &birth,
d0cd7f09 1424 tfc->t_context->index,
a56a1ba4 1425 &y_in,
1426 &height,
14963be0 1427 &hashed_process_data_in);
a56a1ba4 1428
ca0f8a8e 1429 drawing_insert_square( control_flow_data->drawing, y_in, height);
a56a1ba4 1430 }
1431 g_free(name);
1432
1433
1434 /* Find pixels corresponding to time of the event. If the time does
1435 * not fit in the window, show a warning, not supposed to happend. */
1436 //guint x = 0;
501d5405 1437 //guint width = control_flow_data->drawing->drawing_area->allocation.width;
a56a1ba4 1438
1439 //LttTime time = ltt_event_time(e);
1440
224446ce 1441 //LttTime window_end = ltt_time_add(time_window->time_width,
1442 // time_window->start_time);
a56a1ba4 1443
1444
1445 //convert_time_to_pixels(
224446ce 1446 // time_window->start_time,
a56a1ba4 1447 // window_end,
1448 // time,
1449 // width,
1450 // &x);
1451
1452 //assert(x <= width);
1453
1454 /* draw what represents the event for outgoing process. */
1455
14963be0 1456 DrawContext *draw_context_out = hashed_process_data_out->draw_context;
68997a22 1457 //draw_context_out->current->modify_over->x = x;
1458 draw_context_out->current->modify_over->y = y_out;
319e9d81 1459 draw_context_out->current->modify_under->y = y_out+(height/2)+2;
501d5405 1460 draw_context_out->drawable = control_flow_data->drawing->pixmap;
1461 draw_context_out->pango_layout = control_flow_data->drawing->pango_layout;
1462 GtkWidget *widget = control_flow_data->drawing->drawing_area;
a56a1ba4 1463 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
d0cd7f09 1464
a56a1ba4 1465 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
501d5405 1466 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
d0cd7f09 1467
1468 /*if(process_out->state->s == LTTV_STATE_RUN)
1469 {
1470 draw_context_out->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1471 gdk_gc_copy(draw_context_out->gc, widget->style->black_gc);
1472 PropertiesBG prop_bg;
1473 prop_bg.color = g_new(GdkColor,1);
1474
1475 prop_bg.color->red = 0xffff;
1476 prop_bg.color->green = 0xffff;
1477 prop_bg.color->blue = 0xffff;
1478
1479 draw_bg((void*)&prop_bg, (void*)draw_context_out);
1480 g_free(prop_bg.color);
1481 gdk_gc_unref(draw_context_out->gc);
1482 }*/
1483
1484 draw_context_out->gc = widget->style->black_gc;
1485
a56a1ba4 1486 GdkColor colorfg_out = { 0, 0xffff, 0x0000, 0x0000 };
2df6f2bd 1487 GdkColor colorbg_out = { 0, 0x0000, 0x0000, 0x0000 };
a56a1ba4 1488 PropertiesText prop_text_out;
1489 prop_text_out.foreground = &colorfg_out;
1490 prop_text_out.background = &colorbg_out;
cfe526b1 1491 prop_text_out.size = 6;
a56a1ba4 1492 prop_text_out.position = OVER;
1493
cfe526b1 1494 /* color of text : status of the process */
1495 if(process_out->state->s == LTTV_STATE_UNNAMED)
1496 {
1497 prop_text_out.foreground->red = 0xffff;
1498 prop_text_out.foreground->green = 0xffff;
1499 prop_text_out.foreground->blue = 0xffff;
1500 }
1501 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
1502 {
1503 prop_text_out.foreground->red = 0x0fff;
d52cfc84 1504 prop_text_out.foreground->green = 0xffff;
1505 prop_text_out.foreground->blue = 0xfff0;
cfe526b1 1506 }
1507 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
1508 {
2df6f2bd 1509 prop_text_out.foreground->red = 0xffff;
1510 prop_text_out.foreground->green = 0xffff;
cfe526b1 1511 prop_text_out.foreground->blue = 0x0000;
1512 }
0828099d 1513 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
cfe526b1 1514 {
1515 prop_text_out.foreground->red = 0xffff;
1516 prop_text_out.foreground->green = 0x0000;
1517 prop_text_out.foreground->blue = 0xffff;
1518 }
1519 else if(process_out->state->s == LTTV_STATE_WAIT)
1520 {
1521 prop_text_out.foreground->red = 0xffff;
1522 prop_text_out.foreground->green = 0x0000;
1523 prop_text_out.foreground->blue = 0x0000;
1524 }
1525 else if(process_out->state->s == LTTV_STATE_RUN)
1526 {
1527 prop_text_out.foreground->red = 0x0000;
1528 prop_text_out.foreground->green = 0xffff;
1529 prop_text_out.foreground->blue = 0x0000;
1530 }
1531 else
1532 {
1533 prop_text_out.foreground->red = 0xffff;
1534 prop_text_out.foreground->green = 0xffff;
1535 prop_text_out.foreground->blue = 0xffff;
1536 }
1537
a56a1ba4 1538 /* Print status of the process : U, WF, WC, E, W, R */
1539 if(process_out->state->s == LTTV_STATE_UNNAMED)
68997a22 1540 prop_text_out.text = "U";
a56a1ba4 1541 else if(process_out->state->s == LTTV_STATE_WAIT_FORK)
68997a22 1542 prop_text_out.text = "WF";
a56a1ba4 1543 else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
68997a22 1544 prop_text_out.text = "WC";
0828099d 1545 else if(process_out->state->s == LTTV_STATE_ZOMBIE)
68997a22 1546 prop_text_out.text = "E";
a56a1ba4 1547 else if(process_out->state->s == LTTV_STATE_WAIT)
68997a22 1548 prop_text_out.text = "W";
a56a1ba4 1549 else if(process_out->state->s == LTTV_STATE_RUN)
68997a22 1550 prop_text_out.text = "R";
a56a1ba4 1551 else
68997a22 1552 prop_text_out.text = "U";
a56a1ba4 1553
1554 draw_text((void*)&prop_text_out, (void*)draw_context_out);
d0cd7f09 1555
1556 //gdk_gc_unref(draw_context_out->gc);
319e9d81 1557
68997a22 1558 draw_context_out->current->middle->y = y_out+height/2;
d0cd7f09 1559 draw_context_out->current->over->y = y_out;
1560 draw_context_out->current->under->y = y_out+height;
68997a22 1561 draw_context_out->current->status = process_out->state->s;
a56a1ba4 1562
68997a22 1563 /* for pid_out : remove previous, Prev = current, new current (default) */
1564 g_free(draw_context_out->previous->modify_under);
1565 g_free(draw_context_out->previous->modify_middle);
1566 g_free(draw_context_out->previous->modify_over);
1567 g_free(draw_context_out->previous->under);
1568 g_free(draw_context_out->previous->middle);
1569 g_free(draw_context_out->previous->over);
1570 g_free(draw_context_out->previous);
1571
1572 draw_context_out->previous = draw_context_out->current;
a56a1ba4 1573
68997a22 1574 draw_context_out->current = g_new(DrawInfo,1);
1575 draw_context_out->current->over = g_new(ItemInfo,1);
1576 draw_context_out->current->over->x = -1;
1577 draw_context_out->current->over->y = -1;
1578 draw_context_out->current->middle = g_new(ItemInfo,1);
1579 draw_context_out->current->middle->x = -1;
1580 draw_context_out->current->middle->y = -1;
1581 draw_context_out->current->under = g_new(ItemInfo,1);
1582 draw_context_out->current->under->x = -1;
1583 draw_context_out->current->under->y = -1;
1584 draw_context_out->current->modify_over = g_new(ItemInfo,1);
1585 draw_context_out->current->modify_over->x = -1;
1586 draw_context_out->current->modify_over->y = -1;
1587 draw_context_out->current->modify_middle = g_new(ItemInfo,1);
1588 draw_context_out->current->modify_middle->x = -1;
1589 draw_context_out->current->modify_middle->y = -1;
1590 draw_context_out->current->modify_under = g_new(ItemInfo,1);
1591 draw_context_out->current->modify_under->x = -1;
1592 draw_context_out->current->modify_under->y = -1;
1593 draw_context_out->current->status = LTTV_STATE_UNNAMED;
a56a1ba4 1594
1595 /* Finally, update the drawing context of the pid_in. */
1596
14963be0 1597 DrawContext *draw_context_in = hashed_process_data_in->draw_context;
68997a22 1598 //draw_context_in->current->modify_over->x = x;
1599 draw_context_in->current->modify_over->y = y_in;
319e9d81 1600 draw_context_in->current->modify_under->y = y_in+(height/2)+2;
501d5405 1601 draw_context_in->drawable = control_flow_data->drawing->pixmap;
1602 draw_context_in->pango_layout = control_flow_data->drawing->pango_layout;
1603 widget = control_flow_data->drawing->drawing_area;
a56a1ba4 1604 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
a56a1ba4 1605
1606 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
501d5405 1607 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
d0cd7f09 1608
1609 /*if(process_in->state->s == LTTV_STATE_RUN)
1610 {
1611 draw_context_in->gc = gdk_gc_new(control_flow_data->drawing->pixmap);
1612 gdk_gc_copy(draw_context_in->gc, widget->style->black_gc);
1613 PropertiesBG prop_bg;
1614 prop_bg.color = g_new(GdkColor,1);
1615
1616 prop_bg.color->red = 0xffff;
1617 prop_bg.color->green = 0xffff;
1618 prop_bg.color->blue = 0xffff;
1619
1620 draw_bg((void*)&prop_bg, (void*)draw_context_in);
1621 g_free(prop_bg.color);
1622 gdk_gc_unref(draw_context_in->gc);
1623 }*/
1624
1625 draw_context_in->gc = widget->style->black_gc;
1626
a56a1ba4 1627 GdkColor colorfg_in = { 0, 0x0000, 0xffff, 0x0000 };
2df6f2bd 1628 GdkColor colorbg_in = { 0, 0x0000, 0x0000, 0x0000 };
a56a1ba4 1629 PropertiesText prop_text_in;
1630 prop_text_in.foreground = &colorfg_in;
1631 prop_text_in.background = &colorbg_in;
cfe526b1 1632 prop_text_in.size = 6;
a56a1ba4 1633 prop_text_in.position = OVER;
1634
cfe526b1 1635 /* foreground of text : status of the process */
1636 if(process_in->state->s == LTTV_STATE_UNNAMED)
1637 {
1638 prop_text_in.foreground->red = 0xffff;
1639 prop_text_in.foreground->green = 0xffff;
1640 prop_text_in.foreground->blue = 0xffff;
1641 }
1642 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
1643 {
1644 prop_text_in.foreground->red = 0x0fff;
d52cfc84 1645 prop_text_in.foreground->green = 0xffff;
1646 prop_text_in.foreground->blue = 0xfff0;
cfe526b1 1647 }
1648 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
1649 {
2df6f2bd 1650 prop_text_in.foreground->red = 0xffff;
1651 prop_text_in.foreground->green = 0xffff;
cfe526b1 1652 prop_text_in.foreground->blue = 0x0000;
1653 }
0828099d 1654 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
cfe526b1 1655 {
1656 prop_text_in.foreground->red = 0xffff;
1657 prop_text_in.foreground->green = 0x0000;
1658 prop_text_in.foreground->blue = 0xffff;
1659 }
1660 else if(process_in->state->s == LTTV_STATE_WAIT)
1661 {
1662 prop_text_in.foreground->red = 0xffff;
1663 prop_text_in.foreground->green = 0x0000;
1664 prop_text_in.foreground->blue = 0x0000;
1665 }
1666 else if(process_in->state->s == LTTV_STATE_RUN)
1667 {
1668 prop_text_in.foreground->red = 0x0000;
1669 prop_text_in.foreground->green = 0xffff;
1670 prop_text_in.foreground->blue = 0x0000;
1671 }
1672 else
1673 {
1674 prop_text_in.foreground->red = 0xffff;
1675 prop_text_in.foreground->green = 0xffff;
1676 prop_text_in.foreground->blue = 0xffff;
1677 }
1678
1679
a56a1ba4 1680 /* Print status of the process : U, WF, WC, E, W, R */
1681 if(process_in->state->s == LTTV_STATE_UNNAMED)
68997a22 1682 prop_text_in.text = "U";
a56a1ba4 1683 else if(process_in->state->s == LTTV_STATE_WAIT_FORK)
68997a22 1684 prop_text_in.text = "WF";
a56a1ba4 1685 else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
68997a22 1686 prop_text_in.text = "WC";
0828099d 1687 else if(process_in->state->s == LTTV_STATE_ZOMBIE)
68997a22 1688 prop_text_in.text = "E";
a56a1ba4 1689 else if(process_in->state->s == LTTV_STATE_WAIT)
68997a22 1690 prop_text_in.text = "W";
a56a1ba4 1691 else if(process_in->state->s == LTTV_STATE_RUN)
68997a22 1692 prop_text_in.text = "R";
a56a1ba4 1693 else
68997a22 1694 prop_text_in.text = "U";
a56a1ba4 1695
1696 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1697
d0cd7f09 1698
319e9d81 1699 if(process_in->state->s == LTTV_STATE_RUN)
1700 {
1701 gchar tmp[255];
1702 prop_text_in.foreground = &colorfg_in;
1703 prop_text_in.background = &colorbg_in;
1704 prop_text_in.foreground->red = 0xffff;
1705 prop_text_in.foreground->green = 0xffff;
1706 prop_text_in.foreground->blue = 0xffff;
1707 prop_text_in.size = 6;
1708 prop_text_in.position = UNDER;
1709
1710 prop_text_in.text = g_new(gchar, 260);
1711 strcpy(prop_text_in.text, "CPU ");
1712 snprintf(tmp, 255, "%u", tfc->index);
1713 strcat(prop_text_in.text, tmp);
1714
1715 draw_text((void*)&prop_text_in, (void*)draw_context_in);
1716 g_free(prop_text_in.text);
1717 }
1718
1719
68997a22 1720 draw_context_in->current->middle->y = y_in+height/2;
d0cd7f09 1721 draw_context_in->current->over->y = y_in;
1722 draw_context_in->current->under->y = y_in+height;
68997a22 1723 draw_context_in->current->status = process_in->state->s;
1724
1725 /* for pid_in : remove previous, Prev = current, new current (default) */
1726 g_free(draw_context_in->previous->modify_under);
1727 g_free(draw_context_in->previous->modify_middle);
1728 g_free(draw_context_in->previous->modify_over);
1729 g_free(draw_context_in->previous->under);
1730 g_free(draw_context_in->previous->middle);
1731 g_free(draw_context_in->previous->over);
1732 g_free(draw_context_in->previous);
1733
1734 draw_context_in->previous = draw_context_in->current;
a56a1ba4 1735
68997a22 1736 draw_context_in->current = g_new(DrawInfo,1);
1737 draw_context_in->current->over = g_new(ItemInfo,1);
1738 draw_context_in->current->over->x = -1;
1739 draw_context_in->current->over->y = -1;
1740 draw_context_in->current->middle = g_new(ItemInfo,1);
1741 draw_context_in->current->middle->x = -1;
1742 draw_context_in->current->middle->y = -1;
1743 draw_context_in->current->under = g_new(ItemInfo,1);
1744 draw_context_in->current->under->x = -1;
1745 draw_context_in->current->under->y = -1;
1746 draw_context_in->current->modify_over = g_new(ItemInfo,1);
1747 draw_context_in->current->modify_over->x = -1;
1748 draw_context_in->current->modify_over->y = -1;
1749 draw_context_in->current->modify_middle = g_new(ItemInfo,1);
1750 draw_context_in->current->modify_middle->x = -1;
1751 draw_context_in->current->modify_middle->y = -1;
1752 draw_context_in->current->modify_under = g_new(ItemInfo,1);
1753 draw_context_in->current->modify_under->x = -1;
1754 draw_context_in->current->modify_under->y = -1;
1755 draw_context_in->current->status = LTTV_STATE_UNNAMED;
a56a1ba4 1756
1757 }
1758
1759 return 0;
b9a010a2 1760#endif //0
f0d936c0 1761}
f7afe191 1762
23093869 1763static __inline PropertiesLine prepare_execmode_line(LttvProcessState *process)
1764{
1765 PropertiesLine prop_line;
1766 prop_line.line_width = 1;
1767 prop_line.style = GDK_LINE_SOLID;
1768 prop_line.y = OVER;
1769 //GdkColormap *colormap = gdk_colormap_get_system();
1770
1771 /* color of line : execution mode of the process */
1772 if(process->state->t == LTTV_STATE_USER_MODE)
1773 prop_line.color = drawing_colors[COL_USER_MODE];
1774 else if(process->state->t == LTTV_STATE_SYSCALL)
1775 prop_line.color = drawing_colors[COL_SYSCALL];
1776 else if(process->state->t == LTTV_STATE_TRAP)
1777 prop_line.color = drawing_colors[COL_TRAP];
1778 else if(process->state->t == LTTV_STATE_IRQ)
1779 prop_line.color = drawing_colors[COL_IRQ];
1780 else if(process->state->t == LTTV_STATE_MODE_UNKNOWN)
1781 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
1782 else
1783 prop_line.color = drawing_colors[COL_WHITE];
1784
1785 //gdk_colormap_alloc_color(colormap,
1786 // prop_line.color,
1787 // FALSE,
1788 // TRUE);
1789
1790 return prop_line;
1791
1792}
1793
1794
1795
1796/* before_execmode_hook
1797 *
1798 * This function basically draw lines and icons. Two types of lines are drawn :
1799 * one small (3 pixels?) representing the state of the process and the second
1800 * type is thicker (10 pixels?) representing on which CPU a process is running
1801 * (and this only in running state).
1802 *
1803 * Extremums of the lines :
1804 * x_min : time of the last event context for this process kept in memory.
1805 * x_max : time of the current event.
1806 * y : middle of the process in the process list. The process is found in the
1807 * list, therefore is it's position in pixels.
1808 *
1809 * The choice of lines'color is defined by the context of the last event for this
1810 * process.
1811 */
1812
1813
1814int before_execmode_hook(void *hook_data, void *call_data)
1815{
1816 EventsRequest *events_request = (EventsRequest*)hook_data;
1817 ControlFlowData *control_flow_data = events_request->viewer_data;
1818 Drawing_t *drawing = control_flow_data->drawing;
1819
1820 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1821
1822 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1823 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
1824
1825 LttEvent *e;
1826 e = tfc->e;
1827
1828 LttTime evtime = ltt_event_time(e);
1829 TimeWindow time_window =
1830 lttvwindow_get_time_window(control_flow_data->tab);
1831
1832 LttTime end_time = ltt_time_add(time_window.start_time,
1833 time_window.time_width);
1834
1835 if(ltt_time_compare(evtime, time_window.start_time) == -1
1836 || ltt_time_compare(evtime, end_time) == 1)
1837 return;
1838
1839 guint width = drawing->width;
1840
10a1069a 1841 /* we are in a execmode, before the state update. We must draw the
1842 * items corresponding to the state before it changes : now is the right
1843 * time to do it.
1844 */
1845 /* For the pid */
1846 LttvProcessState *process = tfs->process;
1847 g_assert(process != NULL);
23093869 1848
10a1069a 1849 guint pid = process->pid;
23093869 1850
10a1069a 1851 /* Well, the process_out existed : we must get it in the process hash
1852 * or add it, and draw its items.
1853 */
1854 /* Add process to process list (if not present) */
1855 guint y = 0, height = 0, pl_height = 0;
1856 HashedProcessData *hashed_process_data = NULL;
1857 ProcessList *process_list =
1858 guicontrolflow_get_process_list(control_flow_data);
1859 LttTime birth = process->creation_time;
1860 const gchar *name = g_quark_to_string(process->name);
1861
1862 if(processlist_get_process_pixels(process_list,
1863 pid,
1864 process->last_cpu,
1865 &birth,
1866 tfc->t_context->index,
1867 &y,
1868 &height,
1869 &hashed_process_data) == 1)
1870 {
1871 g_assert(pid == 0 || pid != process->ppid);
1872 /* Process not present */
1873 processlist_add(process_list,
1874 pid,
1875 process->last_cpu,
1876 process->ppid,
1877 &birth,
1878 tfc->t_context->index,
1879 name,
1880 &pl_height,
1881 &hashed_process_data);
1882 processlist_get_process_pixels(process_list,
dbd243b1 1883 pid,
1884 process->last_cpu,
1885 &birth,
1886 tfc->t_context->index,
1887 &y,
1888 &height,
10a1069a 1889 &hashed_process_data);
1890 drawing_insert_square( drawing, y, height);
1891 }
23093869 1892
10a1069a 1893 /* Now, the process is in the state hash and our own process hash.
1894 * We definitely can draw the items related to the ending state.
1895 */
1896
1897 /* Check if the x position is unset. In can have been left unset by
1898 * a draw closure from a after chunk hook. This should never happen,
1899 * because it must be set by before chunk hook to the damage_begin
1900 * value.
1901 */
1902 g_assert(hashed_process_data->x.over != -1);
1903 {
1904 guint x;
1905 DrawContext draw_context;
dbd243b1 1906
10a1069a 1907 convert_time_to_pixels(
1908 time_window.start_time,
1909 end_time,
1910 evtime,
1911 width,
1912 &x);
dbd243b1 1913
10a1069a 1914 /* Now create the drawing context that will be used to draw
1915 * items related to the last state. */
1916 draw_context.drawable = drawing->pixmap;
1917 draw_context.gc = drawing->gc;
1918 draw_context.pango_layout = drawing->pango_layout;
1919 draw_context.drawinfo.start.x = hashed_process_data->x.over;
1920 draw_context.drawinfo.end.x = x;
1921
1922 draw_context.drawinfo.y.over = y+1;
1923 draw_context.drawinfo.y.middle = y+(height/2);
1924 draw_context.drawinfo.y.under = y+height;
1925
1926 draw_context.drawinfo.start.offset.over = 0;
1927 draw_context.drawinfo.start.offset.middle = 0;
1928 draw_context.drawinfo.start.offset.under = 0;
1929 draw_context.drawinfo.end.offset.over = 0;
1930 draw_context.drawinfo.end.offset.middle = 0;
1931 draw_context.drawinfo.end.offset.under = 0;
23093869 1932
10a1069a 1933 {
1934 /* Draw the line */
1935 PropertiesLine prop_line = prepare_execmode_line(process);
1936 draw_line((void*)&prop_line, (void*)&draw_context);
23093869 1937
23093869 1938 }
10a1069a 1939 /* become the last x position */
1940 hashed_process_data->x.over = x;
23093869 1941 }
1942
1943 return 0;
1944}
1945
1946/* after_execmode_hook
1947 *
1948 * The draw after hook is called by the reading API to have a
1949 * particular event drawn on the screen.
1950 * @param hook_data ControlFlowData structure of the viewer.
1951 * @param call_data Event context.
1952 *
1953 * This function adds items to be drawn in a queue for each process.
1954 *
1955 */
1956int after_execmode_hook(void *hook_data, void *call_data)
1957{
1958 EventsRequest *events_request = (EventsRequest*)hook_data;
1959 ControlFlowData *control_flow_data = events_request->viewer_data;
1960
1961 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1962
1963 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1964 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
1965
1966 LttEvent *e;
1967 e = tfc->e;
1968
1969 LttTime evtime = ltt_event_time(e);
1970 TimeWindow time_window =
1971 lttvwindow_get_time_window(control_flow_data->tab);
1972
1973 LttTime end_time = ltt_time_add(time_window.start_time,
1974 time_window.time_width);
1975
1976 if(ltt_time_compare(evtime, time_window.start_time) == -1
1977 || ltt_time_compare(evtime, end_time) == 1)
1978 return;
1979
1980 guint width = control_flow_data->drawing->width;
1981
10a1069a 1982 /* Add process to process list (if not present) */
1983 LttvProcessState *process;
1984 LttTime birth;
1985 guint y = 0, height = 0, pl_height = 0;
1986 HashedProcessData *hashed_process_data = NULL;
23093869 1987
10a1069a 1988 ProcessList *process_list =
1989 guicontrolflow_get_process_list(control_flow_data);
1990
23093869 1991
10a1069a 1992 /* Find process pid_in in the list... */
1993 process = tfs->process;
1994 /* It should exist, because we are after the state update. */
1995 g_assert(process != NULL);
23093869 1996
10a1069a 1997 guint pid = process->pid;
23093869 1998
10a1069a 1999 birth = process->creation_time;
2000 const gchar *name = g_quark_to_string(process->name);
23093869 2001
10a1069a 2002 if(processlist_get_process_pixels(process_list,
2003 pid,
2004 process->last_cpu,
2005 &birth,
2006 tfc->t_context->index,
2007 &y,
2008 &height,
2009 &hashed_process_data) == 1)
2010 {
2011 g_assert(pid == 0 || pid != process->ppid);
2012 /* Process not present */
2013 processlist_add(process_list,
2014 pid,
2015 process->last_cpu,
2016 process->ppid,
2017 &birth,
2018 tfc->t_context->index,
2019 name,
2020 &pl_height,
2021 &hashed_process_data);
2022 processlist_get_process_pixels(process_list,
23093869 2023 pid,
2024 process->last_cpu,
23093869 2025 &birth,
2026 tfc->t_context->index,
10a1069a 2027 &y,
2028 &height,
23093869 2029 &hashed_process_data);
10a1069a 2030 drawing_insert_square( control_flow_data->drawing, y, height);
23093869 2031 }
10a1069a 2032
2033 convert_time_to_pixels(
2034 time_window.start_time,
2035 end_time,
2036 evtime,
2037 width,
2038 &hashed_process_data->x.over);
23093869 2039 return 0;
2040}
2041
2042
dbd243b1 2043
2044/* before_process_hook
2045 *
2046 * Draw lines for process event.
2047 *
2048 * @param hook_data ControlFlowData structure of the viewer.
2049 * @param call_data Event context.
2050 *
2051 * This function adds items to be drawn in a queue for each process.
2052 *
2053 */
2054int before_process_hook(void *hook_data, void *call_data)
2055{
2056 EventsRequest *events_request = (EventsRequest*)hook_data;
2057 ControlFlowData *control_flow_data = events_request->viewer_data;
2058 Drawing_t *drawing = control_flow_data->drawing;
2059
2060 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2061
2062 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2063 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
2064
2065 LttEvent *e;
2066 e = tfc->e;
2067
2068 LttTime evtime = ltt_event_time(e);
2069 TimeWindow time_window =
2070 lttvwindow_get_time_window(control_flow_data->tab);
2071
2072 LttTime end_time = ltt_time_add(time_window.start_time,
2073 time_window.time_width);
2074
2075 if(ltt_time_compare(evtime, time_window.start_time) == -1
2076 || ltt_time_compare(evtime, end_time) == 1)
2077 return;
2078
2079 guint width = control_flow_data->drawing->width;
2080
10a1069a 2081 guint sub_id;
2082 {
2083 LttField *f = ltt_event_field(e);
2084 LttField *element;
2085 element = ltt_field_member(f,0);
2086 sub_id = ltt_event_get_long_unsigned(e,element);
2087 }
dbd243b1 2088
10a1069a 2089 if(sub_id == 3) { /* exit */
dbd243b1 2090
10a1069a 2091 /* Add process to process list (if not present) */
2092 LttvProcessState *process = tfs->process;
2093 guint pid = process->pid;
2094 LttTime birth;
2095 guint y = 0, height = 0, pl_height = 0;
2096 HashedProcessData *hashed_process_data = NULL;
dbd243b1 2097
10a1069a 2098 ProcessList *process_list =
2099 guicontrolflow_get_process_list(control_flow_data);
2100
2101 g_assert(process != NULL);
dbd243b1 2102
10a1069a 2103 birth = process->creation_time;
2104 const gchar *name = g_quark_to_string(process->name);
dbd243b1 2105
10a1069a 2106 if(processlist_get_process_pixels(process_list,
2107 pid,
2108 process->last_cpu,
2109 &birth,
2110 tfc->t_context->index,
2111 &y,
2112 &height,
2113 &hashed_process_data) == 1)
2114 {
2115 g_assert(pid == 0 || pid != process->ppid);
2116 /* Process not present */
2117 processlist_add(process_list,
2118 pid,
2119 process->last_cpu,
2120 process->ppid,
2121 &birth,
2122 tfc->t_context->index,
2123 name,
2124 &pl_height,
2125 &hashed_process_data);
2126 processlist_get_process_pixels(process_list,
dbd243b1 2127 pid,
2128 process->last_cpu,
2129 &birth,
2130 tfc->t_context->index,
2131 &y,
2132 &height,
10a1069a 2133 &hashed_process_data);
2134 drawing_insert_square( control_flow_data->drawing, y, height);
2135 }
dbd243b1 2136
10a1069a 2137 /* Now, the process is in the state hash and our own process hash.
2138 * We definitely can draw the items related to the ending state.
2139 */
2140
2141 /* Check if the x position is unset. In can have been left unset by
2142 * a draw closure from a after chunk hook. This should never happen,
2143 * because it must be set by before chunk hook to the damage_begin
2144 * value.
2145 */
2146 g_assert(hashed_process_data->x.over != -1);
2147 {
2148 guint x;
2149 DrawContext draw_context;
dbd243b1 2150
10a1069a 2151 convert_time_to_pixels(
2152 time_window.start_time,
2153 end_time,
2154 evtime,
2155 width,
2156 &x);
dbd243b1 2157
10a1069a 2158 /* Now create the drawing context that will be used to draw
2159 * items related to the last state. */
2160 draw_context.drawable = drawing->pixmap;
2161 draw_context.gc = drawing->gc;
2162 draw_context.pango_layout = drawing->pango_layout;
2163 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
2164 draw_context.drawinfo.end.x = x;
dbd243b1 2165
10a1069a 2166 draw_context.drawinfo.y.over = y+1;
2167 draw_context.drawinfo.y.middle = y+(height/2);
2168 draw_context.drawinfo.y.under = y+height;
dbd243b1 2169
10a1069a 2170 draw_context.drawinfo.start.offset.over = 0;
2171 draw_context.drawinfo.start.offset.middle = 0;
2172 draw_context.drawinfo.start.offset.under = 0;
2173 draw_context.drawinfo.end.offset.over = 0;
2174 draw_context.drawinfo.end.offset.middle = 0;
2175 draw_context.drawinfo.end.offset.under = 0;
dbd243b1 2176
10a1069a 2177 {
2178 /* Draw the line */
2179 PropertiesLine prop_line = prepare_status_line(process);
2180 draw_line((void*)&prop_line, (void*)&draw_context);
dbd243b1 2181
dbd243b1 2182 }
10a1069a 2183 /* become the last x position */
2184 hashed_process_data->x.middle = x;
dbd243b1 2185 }
2186
dbd243b1 2187 }
2188 return 0;
2189
2190}
2191
2192
2193
2194
2195
2196
2197/* after_process_hook
e92eabaf 2198 *
2199 * Create the processlist entry for the child process. Put the last
2200 * position in x at the current time value.
2201 *
2202 * @param hook_data ControlFlowData structure of the viewer.
2203 * @param call_data Event context.
2204 *
2205 * This function adds items to be drawn in a queue for each process.
2206 *
2207 */
dbd243b1 2208int after_process_hook(void *hook_data, void *call_data)
e92eabaf 2209{
2210 EventsRequest *events_request = (EventsRequest*)hook_data;
2211 ControlFlowData *control_flow_data = events_request->viewer_data;
2212
2213 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2214
2215 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2216 LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
2217
2218 LttEvent *e;
2219 e = tfc->e;
2220
2221 LttTime evtime = ltt_event_time(e);
2222 TimeWindow time_window =
2223 lttvwindow_get_time_window(control_flow_data->tab);
2224
2225 LttTime end_time = ltt_time_add(time_window.start_time,
2226 time_window.time_width);
2227
2228 if(ltt_time_compare(evtime, time_window.start_time) == -1
2229 || ltt_time_compare(evtime, end_time) == 1)
2230 return;
f7afe191 2231
e92eabaf 2232 guint width = control_flow_data->drawing->width;
2233
10a1069a 2234 guint sub_id;
2235 guint param1;
2236 {
2237 LttField *f = ltt_event_field(e);
2238 LttField *element;
2239 element = ltt_field_member(f,0);
2240 sub_id = ltt_event_get_long_unsigned(e,element);
2241 element = ltt_field_member(f,1);
2242 param1 = ltt_event_get_long_unsigned(e,element);
2243 }
e92eabaf 2244
10a1069a 2245 if(sub_id == 2) { /* fork */
2246
2247 guint child_pid = param1;
2248 /* Add process to process list (if not present) */
2249 LttvProcessState *process_child;
2250 LttTime birth;
2251 guint y_child = 0, height = 0, pl_height = 0;
2252 HashedProcessData *hashed_process_data_child = NULL;
e92eabaf 2253
10a1069a 2254 ProcessList *process_list =
2255 guicontrolflow_get_process_list(control_flow_data);
2256
e92eabaf 2257
10a1069a 2258 /* Find child in the list... */
2259 process_child = lttv_state_find_process(tfs, child_pid);
2260 /* It should exist, because we are after the state update. */
2261 g_assert(process_child != NULL);
e92eabaf 2262
10a1069a 2263 birth = process_child->creation_time;
2264 const gchar *name = g_quark_to_string(process_child->name);
e92eabaf 2265
10a1069a 2266 if(processlist_get_process_pixels(process_list,
2267 child_pid,
2268 process_child->last_cpu,
2269 &birth,
2270 tfc->t_context->index,
2271 &y_child,
2272 &height,
2273 &hashed_process_data_child) == 1)
2274 {
2275 g_assert(child_pid == 0 || child_pid != process_child->ppid);
2276 /* Process not present */
2277 processlist_add(process_list,
2278 child_pid,
2279 process_child->last_cpu,
2280 process_child->ppid,
2281 &birth,
2282 tfc->t_context->index,
2283 name,
2284 &pl_height,
2285 &hashed_process_data_child);
2286 processlist_get_process_pixels(process_list,
e92eabaf 2287 child_pid,
a95bc95a 2288 process_child->last_cpu,
e92eabaf 2289 &birth,
2290 tfc->t_context->index,
2291 &y_child,
2292 &height,
10a1069a 2293 &hashed_process_data_child);
2294 drawing_insert_square( control_flow_data->drawing, y_child, height);
2295 }
e92eabaf 2296
10a1069a 2297 guint new_x;
2298 convert_time_to_pixels(
2299 time_window.start_time,
2300 end_time,
2301 evtime,
2302 width,
2303 &new_x);
2304 hashed_process_data_child->x.over = new_x;
2305 hashed_process_data_child->x.middle = new_x;
2306 hashed_process_data_child->x.under = new_x;
23093869 2307
10a1069a 2308 } else if(sub_id == 3) { /* exit */
dbd243b1 2309
10a1069a 2310 /* Add process to process list (if not present) */
2311 LttvProcessState *process = tfs->process;
2312 guint pid = process->pid;
2313 LttTime birth;
2314 guint y = 0, height = 0, pl_height = 0;
2315 HashedProcessData *hashed_process_data = NULL;
dbd243b1 2316
10a1069a 2317 ProcessList *process_list =
2318 guicontrolflow_get_process_list(control_flow_data);
2319
dbd243b1 2320
10a1069a 2321 /* It should exist, because we are after the state update. */
2322 g_assert(process != NULL);
dbd243b1 2323
10a1069a 2324 birth = process->creation_time;
2325 const gchar *name = g_quark_to_string(process->name);
dbd243b1 2326
10a1069a 2327 if(processlist_get_process_pixels(process_list,
2328 pid,
2329 process->last_cpu,
2330 &birth,
2331 tfc->t_context->index,
2332 &y,
2333 &height,
2334 &hashed_process_data) == 1)
2335 {
2336 g_assert(pid == 0 || pid != process->ppid);
2337 /* Process not present */
2338 processlist_add(process_list,
2339 pid,
2340 process->last_cpu,
2341 process->ppid,
2342 &birth,
2343 tfc->t_context->index,
2344 name,
2345 &pl_height,
2346 &hashed_process_data);
2347 processlist_get_process_pixels(process_list,
dbd243b1 2348 pid,
2349 process->last_cpu,
2350 &birth,
2351 tfc->t_context->index,
2352 &y,
2353 &height,
10a1069a 2354 &hashed_process_data);
2355 drawing_insert_square( control_flow_data->drawing, y, height);
e92eabaf 2356 }
dbd243b1 2357
10a1069a 2358 guint new_x;
2359 convert_time_to_pixels(
2360 time_window.start_time,
2361 end_time,
2362 evtime,
2363 width,
2364 &new_x);
2365 hashed_process_data->x.middle = new_x;
e92eabaf 2366 }
2367 return 0;
2368
2369}
f7afe191 2370
2371
1b238973 2372gint update_time_window_hook(void *hook_data, void *call_data)
f7afe191 2373{
a56a1ba4 2374 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
a43d67ba 2375 Drawing_t *drawing = control_flow_data->drawing;
2376
224446ce 2377 const TimeWindowNotifyData *time_window_nofify_data =
2378 ((const TimeWindowNotifyData *)call_data);
2379
14963be0 2380 TimeWindow *old_time_window =
224446ce 2381 time_window_nofify_data->old_time_window;
2382 TimeWindow *new_time_window =
2383 time_window_nofify_data->new_time_window;
a56a1ba4 2384
3cb8b205 2385 /* Update the ruler */
2386 drawing_update_ruler(control_flow_data->drawing,
2387 new_time_window);
2388
2389
a56a1ba4 2390 /* Two cases : zoom in/out or scrolling */
2391
2392 /* In order to make sure we can reuse the old drawing, the scale must
2393 * be the same and the new time interval being partly located in the
2394 * currently shown time interval. (reuse is only for scrolling)
2395 */
2396
2397 g_info("Old time window HOOK : %u, %u to %u, %u",
14963be0 2398 old_time_window->start_time.tv_sec,
2399 old_time_window->start_time.tv_nsec,
2400 old_time_window->time_width.tv_sec,
2401 old_time_window->time_width.tv_nsec);
a56a1ba4 2402
2403 g_info("New time window HOOK : %u, %u to %u, %u",
14963be0 2404 new_time_window->start_time.tv_sec,
2405 new_time_window->start_time.tv_nsec,
2406 new_time_window->time_width.tv_sec,
2407 new_time_window->time_width.tv_nsec);
a56a1ba4 2408
14963be0 2409 if( new_time_window->time_width.tv_sec == old_time_window->time_width.tv_sec
2410 && new_time_window->time_width.tv_nsec == old_time_window->time_width.tv_nsec)
a56a1ba4 2411 {
2412 /* Same scale (scrolling) */
2413 g_info("scrolling");
14963be0 2414 LttTime *ns = &new_time_window->start_time;
2415 LttTime *os = &old_time_window->start_time;
2416 LttTime old_end = ltt_time_add(old_time_window->start_time,
2417 old_time_window->time_width);
2418 LttTime new_end = ltt_time_add(new_time_window->start_time,
2419 new_time_window->time_width);
a56a1ba4 2420 //if(ns<os+w<ns+w)
2421 //if(ns<os+w && os+w<ns+w)
2422 //if(ns<old_end && os<ns)
2423 if(ltt_time_compare(*ns, old_end) == -1
2424 && ltt_time_compare(*os, *ns) == -1)
2425 {
2426 g_info("scrolling near right");
2427 /* Scroll right, keep right part of the screen */
2428 guint x = 0;
51705146 2429 guint width = control_flow_data->drawing->width;
a56a1ba4 2430 convert_time_to_pixels(
2431 *os,
2432 old_end,
2433 *ns,
2434 width,
2435 &x);
2436
2437 /* Copy old data to new location */
501d5405 2438 gdk_draw_drawable (control_flow_data->drawing->pixmap,
cfe526b1 2439 control_flow_data->drawing->drawing_area->style->black_gc,
501d5405 2440 control_flow_data->drawing->pixmap,
a56a1ba4 2441 x, 0,
2442 0, 0,
6395d57c 2443 control_flow_data->drawing->width-x+SAFETY, -1);
2444
2445 if(drawing->damage_begin == drawing->damage_end)
2446 drawing->damage_begin = control_flow_data->drawing->width-x;
2447 else
2448 drawing->damage_begin = 0;
2449
2450 drawing->damage_end = control_flow_data->drawing->width;
2451
a56a1ba4 2452 /* Clear the data request background, but not SAFETY */
501d5405 2453 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
6395d57c 2454 //control_flow_data->drawing->drawing_area->style->black_gc,
cfe526b1 2455 control_flow_data->drawing->drawing_area->style->black_gc,
a56a1ba4 2456 TRUE,
6395d57c 2457 drawing->damage_begin+SAFETY, 0,
2458 drawing->damage_end - drawing->damage_begin, // do not overlap
51705146 2459 control_flow_data->drawing->height);
a43d67ba 2460
51705146 2461 gtk_widget_queue_draw_area (drawing->drawing_area,
a43d67ba 2462 0,0,
6395d57c 2463 control_flow_data->drawing->width,
a43d67ba 2464 control_flow_data->drawing->height);
2465
a56a1ba4 2466 /* Get new data for the rest. */
501d5405 2467 drawing_data_request(control_flow_data->drawing,
2468 &control_flow_data->drawing->pixmap,
6395d57c 2469 drawing->damage_begin, 0,
2470 drawing->damage_end - drawing->damage_begin,
501d5405 2471 control_flow_data->drawing->height);
a56a1ba4 2472 } else {
2473 //if(ns<os<ns+w)
2474 //if(ns<os && os<ns+w)
2475 //if(ns<os && os<new_end)
2476 if(ltt_time_compare(*ns,*os) == -1
2477 && ltt_time_compare(*os,new_end) == -1)
2478 {
2479 g_info("scrolling near left");
2480 /* Scroll left, keep left part of the screen */
2481 guint x = 0;
51705146 2482 guint width = control_flow_data->drawing->width;
a56a1ba4 2483 convert_time_to_pixels(
2484 *ns,
2485 new_end,
2486 *os,
2487 width,
2488 &x);
6395d57c 2489
2490
a56a1ba4 2491 /* Copy old data to new location */
501d5405 2492 gdk_draw_drawable (control_flow_data->drawing->pixmap,
cfe526b1 2493 control_flow_data->drawing->drawing_area->style->black_gc,
501d5405 2494 control_flow_data->drawing->pixmap,
a56a1ba4 2495 0, 0,
2496 x, 0,
2497 -1, -1);
2498
6395d57c 2499 if(drawing->damage_begin == drawing->damage_end)
2500 drawing->damage_end = x;
2501 else
2502 drawing->damage_end =
51705146 2503 control_flow_data->drawing->width;
6395d57c 2504
2505 drawing->damage_begin = 0;
2506
501d5405 2507 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
cfe526b1 2508 control_flow_data->drawing->drawing_area->style->black_gc,
a56a1ba4 2509 TRUE,
6395d57c 2510 drawing->damage_begin, 0,
2511 drawing->damage_end - drawing->damage_begin, // do not overlap
51705146 2512 control_flow_data->drawing->height);
a43d67ba 2513
6395d57c 2514 gtk_widget_queue_draw_area (drawing->drawing_area,
2515 0,0,
2516 control_flow_data->drawing->width,
a43d67ba 2517 control_flow_data->drawing->height);
2518
6395d57c 2519
a56a1ba4 2520 /* Get new data for the rest. */
501d5405 2521 drawing_data_request(control_flow_data->drawing,
2522 &control_flow_data->drawing->pixmap,
6395d57c 2523 drawing->damage_begin, 0,
2524 drawing->damage_end - drawing->damage_begin,
501d5405 2525 control_flow_data->drawing->height);
a56a1ba4 2526
a56a1ba4 2527 } else {
a43d67ba 2528 if(ltt_time_compare(*ns,*os) == 0)
2529 {
2530 g_info("not scrolling");
2531 } else {
2532 g_info("scrolling far");
2533 /* Cannot reuse any part of the screen : far jump */
2534
2535
2536 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
2537 control_flow_data->drawing->drawing_area->style->black_gc,
2538 TRUE,
a56a1ba4 2539 0, 0,
a43d67ba 2540 control_flow_data->drawing->width+SAFETY, // do not overlap
51705146 2541 control_flow_data->drawing->height);
a43d67ba 2542
2543 gtk_widget_queue_draw_area (drawing->drawing_area,
2544 0,0,
2545 control_flow_data->drawing->width,
2546 control_flow_data->drawing->height);
2547
6395d57c 2548 drawing->damage_begin = 0;
2549 drawing->damage_end = control_flow_data->drawing->width;
2550
a43d67ba 2551 drawing_data_request(control_flow_data->drawing,
2552 &control_flow_data->drawing->pixmap,
2553 0, 0,
2554 control_flow_data->drawing->width,
2555 control_flow_data->drawing->height);
2556
2557 }
a56a1ba4 2558 }
2559 }
2560 } else {
2561 /* Different scale (zoom) */
2562 g_info("zoom");
2563
501d5405 2564 gdk_draw_rectangle (control_flow_data->drawing->pixmap,
cfe526b1 2565 control_flow_data->drawing->drawing_area->style->black_gc,
a56a1ba4 2566 TRUE,
2567 0, 0,
501d5405 2568 control_flow_data->drawing->width+SAFETY, // do not overlap
51705146 2569 control_flow_data->drawing->height);
a56a1ba4 2570
a43d67ba 2571 gtk_widget_queue_draw_area (drawing->drawing_area,
2572 0,0,
2573 control_flow_data->drawing->width,
2574 control_flow_data->drawing->height);
a56a1ba4 2575
6395d57c 2576 drawing->damage_begin = 0;
2577 drawing->damage_end = control_flow_data->drawing->width;
2578
501d5405 2579 drawing_data_request(control_flow_data->drawing,
2580 &control_flow_data->drawing->pixmap,
a56a1ba4 2581 0, 0,
501d5405 2582 control_flow_data->drawing->width,
2583 control_flow_data->drawing->height);
a56a1ba4 2584 }
2585
3cb8b205 2586
2587
a56a1ba4 2588 return 0;
f7afe191 2589}
2590
6395d57c 2591gint traceset_notify(void *hook_data, void *call_data)
2592{
2593 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2594 Drawing_t *drawing = control_flow_data->drawing;
2595 GtkWidget *widget = drawing->drawing_area;
2596
6395d57c 2597
b9a010a2 2598 drawing_clear(control_flow_data->drawing);
2599 processlist_clear(control_flow_data->process_list);
d9267eec 2600 redraw_notify(control_flow_data, NULL);
6395d57c 2601
d9267eec 2602 request_background_data(control_flow_data);
2603#if 0
2604 drawing->damage_begin = 0;
2605 drawing->damage_end = drawing->width;
6395d57c 2606 if(drawing->damage_begin < drawing->damage_end)
2607 {
2608 drawing_data_request(drawing,
2609 &drawing->pixmap,
2610 drawing->damage_begin,
2611 0,
2612 drawing->damage_end-drawing->damage_begin,
51705146 2613 drawing->height);
6395d57c 2614 }
2615
2616 gtk_widget_queue_draw_area(drawing->drawing_area,
2617 0,0,
2618 drawing->width,
2619 drawing->height);
d9267eec 2620#endif //0
6395d57c 2621
2622 return FALSE;
2623}
2624
ca0f8a8e 2625gint redraw_notify(void *hook_data, void *call_data)
2626{
2627 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2628 Drawing_t *drawing = control_flow_data->drawing;
2629 GtkWidget *widget = drawing->drawing_area;
2630
2631 drawing->damage_begin = 0;
51705146 2632 drawing->damage_end = drawing->width;
ca0f8a8e 2633
49217bd4 2634 /* fun feature, to be separated someday... */
2635 drawing_clear(control_flow_data->drawing);
2636 processlist_clear(control_flow_data->process_list);
ca0f8a8e 2637
2638 // Clear the image
2639 gdk_draw_rectangle (drawing->pixmap,
2640 widget->style->black_gc,
2641 TRUE,
2642 0, 0,
51705146 2643 drawing->width+SAFETY,
2644 drawing->height);
ca0f8a8e 2645
2646
2647 if(drawing->damage_begin < drawing->damage_end)
2648 {
2649 drawing_data_request(drawing,
2650 &drawing->pixmap,
2651 drawing->damage_begin,
2652 0,
2653 drawing->damage_end-drawing->damage_begin,
51705146 2654 drawing->height);
ca0f8a8e 2655 }
2656
2657 gtk_widget_queue_draw_area(drawing->drawing_area,
2658 0,0,
2659 drawing->width,
2660 drawing->height);
ca0f8a8e 2661 return FALSE;
2662
2663}
2664
2665
2666gint continue_notify(void *hook_data, void *call_data)
a43d67ba 2667{
2668 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
ca0f8a8e 2669 Drawing_t *drawing = control_flow_data->drawing;
2670 GtkWidget *widget = drawing->drawing_area;
a43d67ba 2671
6395d57c 2672 //g_assert(widget->allocation.width == drawing->damage_end);
ca0f8a8e 2673
2674 if(drawing->damage_begin < drawing->damage_end)
2675 {
2676 drawing_data_request(drawing,
2677 &drawing->pixmap,
2678 drawing->damage_begin,
2679 0,
2680 drawing->damage_end-drawing->damage_begin,
51705146 2681 drawing->height);
ca0f8a8e 2682 }
2683
2684 return FALSE;
2685}
2686
2687
1b238973 2688gint update_current_time_hook(void *hook_data, void *call_data)
f7afe191 2689{
14963be0 2690 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
a43d67ba 2691 Drawing_t *drawing = control_flow_data->drawing;
a56a1ba4 2692
224446ce 2693 LttTime current_time = *((LttTime*)call_data);
a56a1ba4 2694
ca0f8a8e 2695 TimeWindow time_window =
2696 lttvwindow_get_time_window(control_flow_data->tab);
a56a1ba4 2697
ca0f8a8e 2698 LttTime time_begin = time_window.start_time;
2699 LttTime width = time_window.time_width;
90ef7e4a 2700 LttTime half_width;
2701 {
2702 guint64 time_ll = ltt_time_to_uint64(width);
2703 time_ll = time_ll >> 1; /* divide by two */
2704 half_width = ltt_time_from_uint64(time_ll);
2705 }
a56a1ba4 2706 LttTime time_end = ltt_time_add(time_begin, width);
2707
2708 LttvTracesetContext * tsc =
ca0f8a8e 2709 lttvwindow_get_traceset_context(control_flow_data->tab);
a56a1ba4 2710
ca0f8a8e 2711 LttTime trace_start = tsc->time_span.start_time;
2712 LttTime trace_end = tsc->time_span.end_time;
a56a1ba4 2713
224446ce 2714 g_info("New current time HOOK : %u, %u", current_time.tv_sec,
2715 current_time.tv_nsec);
a56a1ba4 2716
2717
2718
2719 /* If current time is inside time interval, just move the highlight
2720 * bar */
2721
2722 /* Else, we have to change the time interval. We have to tell it
2723 * to the main window. */
2724 /* The time interval change will take care of placing the current
2725 * time at the center of the visible area, or nearest possible if we are
2726 * at one end of the trace. */
2727
2728
224446ce 2729 if(ltt_time_compare(current_time, time_begin) == -1)
a56a1ba4 2730 {
224446ce 2731 TimeWindow new_time_window;
2732
2733 if(ltt_time_compare(current_time,
a56a1ba4 2734 ltt_time_add(trace_start,half_width)) == -1)
2735 time_begin = trace_start;
2736 else
224446ce 2737 time_begin = ltt_time_sub(current_time,half_width);
a56a1ba4 2738
224446ce 2739 new_time_window.start_time = time_begin;
2740 new_time_window.time_width = width;
a56a1ba4 2741
e800cf84 2742 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
a56a1ba4 2743 }
224446ce 2744 else if(ltt_time_compare(current_time, time_end) == 1)
a56a1ba4 2745 {
224446ce 2746 TimeWindow new_time_window;
2747
2748 if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) == 1)
a56a1ba4 2749 time_begin = ltt_time_sub(trace_end,width);
2750 else
224446ce 2751 time_begin = ltt_time_sub(current_time,half_width);
a56a1ba4 2752
224446ce 2753 new_time_window.start_time = time_begin;
2754 new_time_window.time_width = width;
a56a1ba4 2755
e800cf84 2756 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
a56a1ba4 2757
2758 }
a43d67ba 2759 //gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
2760 gtk_widget_queue_draw_area(drawing->drawing_area,
2761 0,0,
2762 drawing->width,
2763 drawing->height);
a56a1ba4 2764
2765 return 0;
f7afe191 2766}
2767
8b90e648 2768typedef struct _ClosureData {
ca0f8a8e 2769 EventsRequest *events_request;
d0cd7f09 2770 LttvTracesetState *tss;
b9a010a2 2771 LttTime end_time;
8b90e648 2772} ClosureData;
a56a1ba4 2773
8b90e648 2774
e800cf84 2775void draw_closure(gpointer key, gpointer value, gpointer user_data)
2776{
a56a1ba4 2777 ProcessInfo *process_info = (ProcessInfo*)key;
2778 HashedProcessData *hashed_process_data = (HashedProcessData*)value;
2779 ClosureData *closure_data = (ClosureData*)user_data;
2780
e800cf84 2781 EventsRequest *events_request = closure_data->events_request;
2782 ControlFlowData *control_flow_data = events_request->viewer_data;
2783 Drawing_t *drawing = control_flow_data->drawing;
a56a1ba4 2784
e800cf84 2785 LttvTracesetState *tss = closure_data->tss;
2786 LttvTracesetContext *tsc = (LttvTracesetContext*)closure_data->tss;
a56a1ba4 2787
e800cf84 2788 LttTime evtime = closure_data->end_time;
2789 TimeWindow time_window =
2790 lttvwindow_get_time_window(control_flow_data->tab);
ca0f8a8e 2791
e800cf84 2792 LttTime end_time = ltt_time_add(time_window.start_time,
2793 time_window.time_width);
ca0f8a8e 2794
e800cf84 2795 if(ltt_time_compare(evtime, time_window.start_time) == -1
2796 || ltt_time_compare(evtime, end_time) == 1)
2797 return;
ca0f8a8e 2798
e800cf84 2799 guint width = drawing->width;
d0cd7f09 2800
e800cf84 2801 {
2802 /* For the process */
2803 /* First, check if the current process is in the state computation
2804 * process list. If it is there, that means we must add it right now and
2805 * draw items from the beginning of the read for it. If it is not
2806 * present, it's a new process and it was not present : it will
2807 * be added after the state update. */
2808 g_assert(lttv_traceset_number(tsc->ts) > 0);
d0cd7f09 2809
e025a729 2810 /* tracefiles[0] is ok here, because we draw for every PID, and
2811 * assume CPU 0 for PID 0 //FIXME */
2812 LttvTracefileState *tfs =
2813 (LttvTracefileState*)tsc->traces[process_info->trace_num]->tracefiles[0];
a56a1ba4 2814
e800cf84 2815 LttvProcessState *process;
e025a729 2816 process = lttv_state_find_process(tfs,
2817 process_info->pid);
a56a1ba4 2818
e800cf84 2819 if(process != NULL) {
2820
2821 /* Only draw for processes that are currently in the trace states */
ad2e83ba 2822
e800cf84 2823 guint y = 0, height = 0, pl_height = 0;
2824 ProcessList *process_list =
2825 guicontrolflow_get_process_list(control_flow_data);
2826 LttTime birth = process_info->birth;
2827
2828 /* Should be alike when background info is ready */
2829 if(control_flow_data->background_info_waiting==0)
2830 g_assert(ltt_time_compare(process->creation_time,
2831 process_info->birth) == 0);
2832 const gchar *name = g_quark_to_string(process->name);
2833
2834 /* process HAS to be present */
2835 g_assert(processlist_get_process_pixels(process_list,
2836 process_info->pid,
a95bc95a 2837 process_info->cpu,
e800cf84 2838 &birth,
2839 process_info->trace_num,
2840 &y,
2841 &height,
2842 &hashed_process_data) != 1);
2843
2844 /* Now, the process is in the state hash and our own process hash.
2845 * We definitely can draw the items related to the ending state.
2846 */
2847
2848 /* Check if the x position is unset. In can have been left unset by
2849 * a draw closure from a after chunk hook. This should never happen,
2850 * because it must be set by before chunk hook to the damage_begin
2851 * value.
2852 */
23093869 2853 g_assert(hashed_process_data->x.over != -1);
e800cf84 2854 {
2855 guint x;
2856 DrawContext draw_context;
a56a1ba4 2857
e800cf84 2858 convert_time_to_pixels(
2859 time_window.start_time,
2860 end_time,
2861 evtime,
2862 width,
2863 &x);
8b90e648 2864
e800cf84 2865 /* Now create the drawing context that will be used to draw
2866 * items related to the last state. */
2867 draw_context.drawable = drawing->pixmap;
2868 draw_context.gc = drawing->gc;
2869 draw_context.pango_layout = drawing->pango_layout;
e800cf84 2870 draw_context.drawinfo.end.x = x;
2871
23093869 2872 draw_context.drawinfo.y.over = y+1;
2873 draw_context.drawinfo.y.middle = y+(height/2);
2874 draw_context.drawinfo.y.under = y+height;
e800cf84 2875
2876 draw_context.drawinfo.start.offset.over = 0;
2877 draw_context.drawinfo.start.offset.middle = 0;
2878 draw_context.drawinfo.start.offset.under = 0;
2879 draw_context.drawinfo.end.offset.over = 0;
2880 draw_context.drawinfo.end.offset.middle = 0;
2881 draw_context.drawinfo.end.offset.under = 0;
2882
2883 {
23093869 2884 draw_context.drawinfo.start.x = hashed_process_data->x.over;
2885 /* Draw the line */
2886 PropertiesLine prop_line = prepare_execmode_line(process);
2887 draw_line((void*)&prop_line, (void*)&draw_context);
2888
2889 }
2890 hashed_process_data->x.over = x;
2891 {
2892 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
e800cf84 2893 /* Draw the line */
e92eabaf 2894 PropertiesLine prop_line = prepare_status_line(process);
e800cf84 2895 draw_line((void*)&prop_line, (void*)&draw_context);
2896
2897 }
2898
e800cf84 2899 /* become the last x position */
23093869 2900 hashed_process_data->x.middle = x;
e800cf84 2901 }
2902 }
2903 }
2904 return;
8b90e648 2905}
2906
b9a010a2 2907int before_chunk(void *hook_data, void *call_data)
2908{
2909 EventsRequest *events_request = (EventsRequest*)hook_data;
2910 LttvTracesetState *tss = LTTV_TRACESET_STATE(call_data);
2911
2912 drawing_chunk_begin(events_request, tss);
2913
2914 return 0;
2915}
2916
2917int before_request(void *hook_data, void *call_data)
ca0f8a8e 2918{
2919 EventsRequest *events_request = (EventsRequest*)hook_data;
2920 LttvTracesetState *tss = LTTV_TRACESET_STATE(call_data);
2921
2922 drawing_data_request_begin(events_request, tss);
2923
2924 return 0;
2925}
2926
2927
8b90e648 2928/*
b9a010a2 2929 * after request is necessary in addition of after chunk in order to draw
2930 * lines until the end of the screen. after chunk just draws lines until
2931 * the last event.
2932 *
8b90e648 2933 * for each process
a56a1ba4 2934 * draw closing line
b9a010a2 2935 * expose
8b90e648 2936 */
b9a010a2 2937int after_request(void *hook_data, void *call_data)
8b90e648 2938{
ca0f8a8e 2939 EventsRequest *events_request = (EventsRequest*)hook_data;
2940 ControlFlowData *control_flow_data = events_request->viewer_data;
2941 LttvTracesetState *tss = LTTV_TRACESET_STATE(call_data);
b9a010a2 2942 LttvTracesetContext *tsc = LTTV_TRACESET_CONTEXT(call_data);
a56a1ba4 2943
2944 ProcessList *process_list =
ca0f8a8e 2945 guicontrolflow_get_process_list(control_flow_data);
b9a010a2 2946 LttTime end_time = events_request->end_time;
2947
2948 ClosureData closure_data;
2949 closure_data.events_request = (EventsRequest*)hook_data;
2950 closure_data.tss = tss;
2951 closure_data.end_time = end_time;
2952
2953 /* Draw last items */
2954 g_hash_table_foreach(process_list->process_hash, draw_closure,
2955 (void*)&closure_data);
2956
2957 /* Request expose */
2958 drawing_request_expose(events_request, tss, end_time);
2959 return 0;
2960}
2961
2962/*
2963 * for each process
2964 * draw closing line
e800cf84 2965 * expose
b9a010a2 2966 */
2967int after_chunk(void *hook_data, void *call_data)
2968{
2969 EventsRequest *events_request = (EventsRequest*)hook_data;
2970 ControlFlowData *control_flow_data = events_request->viewer_data;
2971 LttvTracesetState *tss = LTTV_TRACESET_STATE(call_data);
2972 LttvTracesetContext *tsc = LTTV_TRACESET_CONTEXT(call_data);
2973 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
2974 LttTime end_time;
2975
2976 ProcessList *process_list =
2977 guicontrolflow_get_process_list(control_flow_data);
2978
e800cf84 2979 if(tfc != NULL)
2980 end_time = LTT_TIME_MIN(tfc->timestamp, events_request->end_time);
0c5dbe3b 2981 else /* end of traceset, or position now out of request : end */
2982 end_time = events_request->end_time;
2983
a56a1ba4 2984 ClosureData closure_data;
ca0f8a8e 2985 closure_data.events_request = (EventsRequest*)hook_data;
2986 closure_data.tss = tss;
b9a010a2 2987 closure_data.end_time = end_time;
a56a1ba4 2988
b9a010a2 2989 /* Draw last items */
14963be0 2990 g_hash_table_foreach(process_list->process_hash, draw_closure,
a56a1ba4 2991 (void*)&closure_data);
a43d67ba 2992
ca0f8a8e 2993 /* Request expose */
b9a010a2 2994 drawing_request_expose(events_request, tss, end_time);
ca0f8a8e 2995
2996 return 0;
8b90e648 2997}
2998
This page took 0.206109 seconds and 4 git commands to generate.