update compat
[lttv.git] / tags / LinuxTraceToolkitViewer-0.10.0-pre-115102007 / lttv / modules / gui / controlflow / drawing.c
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 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <gtk/gtk.h>
24 #include <gdk/gdk.h>
25 #include <string.h>
26
27 #include <ltt/trace.h>
28
29 #include <lttv/lttv.h>
30 #include <lttv/tracecontext.h>
31 #include <lttvwindow/lttvwindow.h>
32 #include <lttv/state.h>
33 #include <lttv/hook.h>
34
35 #include "drawing.h"
36 #include "eventhooks.h"
37 #include "cfv.h"
38
39 #define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
40
41 //FIXME
42 // fixed #define TRACE_NUMBER 0
43 #define EXTRA_ALLOC 1024 // pixels
44
45
46 #if 0 /* colors for two lines representation */
47 GdkColor drawing_colors[NUM_COLORS] =
48 { /* Pixel, R, G, B */
49 { 0, 0, 0, 0 }, /* COL_BLACK */
50 { 0, 0xFFFF, 0xFFFF, 0xFFFF }, /* COL_WHITE */
51 { 0, 0x0FFF, 0xFFFF, 0xFFFF }, /* COL_WAIT_FORK : pale blue */
52 { 0, 0xFFFF, 0xFFFF, 0x0000 }, /* COL_WAIT_CPU : yellow */
53 { 0, 0xFFFF, 0xA000, 0xFCFF }, /* COL_EXIT : pale magenta */
54 { 0, 0xFFFF, 0x0000, 0xFFFF }, /* COL_ZOMBIE : purple */
55 { 0, 0xFFFF, 0x0000, 0x0000 }, /* COL_WAIT : red */
56 { 0, 0x0000, 0xFFFF, 0x0000 }, /* COL_RUN : green */
57 { 0, 0x8800, 0xFFFF, 0x8A00 }, /* COL_USER_MODE : pale green */
58 { 0, 0x09FF, 0x01FF, 0xFFFF }, /* COL_SYSCALL : blue */
59 { 0, 0xF900, 0x4200, 0xFF00 }, /* COL_TRAP : pale purple */
60 { 0, 0xFFFF, 0x5AFF, 0x01FF }, /* COL_IRQ : orange */
61 { 0, 0xFFFF, 0xFFFF, 0xFFFF } /* COL_MODE_UNKNOWN : white */
62
63 };
64 #endif //0
65
66
67 GdkColor drawing_colors[NUM_COLORS] =
68 { /* Pixel, R, G, B */
69 { 0, 0, 0, 0 }, /* COL_BLACK */
70 { 0, 0xFFFF, 0xFFFF, 0xFFFF }, /* COL_WHITE */
71 { 0, 0x0000, 0xFF00, 0x0000 }, /* COL_RUN_USER_MODE : green */
72 { 0, 0x0100, 0x9E00, 0xFFFF }, /* COL_RUN_SYSCALL : pale blue */
73 { 0, 0xFF00, 0xFF00, 0x0100 }, /* COL_RUN_TRAP : yellow */
74 { 0, 0xFFFF, 0x5E00, 0x0000 }, /* COL_RUN_IRQ : orange */
75 { 0, 0xFFFF, 0x9400, 0x9600 }, /* COL_RUN_SOFT_IRQ : pink */
76 { 0, 0x6600, 0x0000, 0x0000 }, /* COL_WAIT : dark red */
77 { 0, 0x7700, 0x7700, 0x0000 }, /* COL_WAIT_CPU : dark yellow */
78 { 0, 0x6400, 0x0000, 0x5D00 }, /* COL_ZOMBIE : dark purple */
79 { 0, 0x0700, 0x6400, 0x0000 }, /* COL_WAIT_FORK : dark green */
80 { 0, 0x8900, 0x0000, 0x8400 }, /* COL_EXIT : "less dark" magenta */
81 { 0, 0xFFFF, 0xFFFF, 0xFFFF }, /* COL_MODE_UNKNOWN : white */
82 { 0, 0xFFFF, 0xFFFF, 0xFFFF } /* COL_UNNAMED : white */
83
84 };
85
86 /*
87 RUN+USER MODE green
88 RUN+SYSCALL
89 RUN+TRAP
90 RUN+IRQ
91 WAIT+foncé
92 WAIT CPU + WAIT FORK vert foncé ou jaune
93 IRQ rouge
94 TRAP: orange
95 SYSCALL: bleu pâle
96
97 ZOMBIE + WAIT EXIT
98 */
99
100
101 /*****************************************************************************
102 * drawing functions *
103 *****************************************************************************/
104
105 static gboolean
106 expose_ruler( GtkWidget *widget, GdkEventExpose *event, gpointer user_data );
107
108 static gboolean
109 motion_notify_ruler(GtkWidget *widget, GdkEventMotion *event, gpointer user_data);
110
111
112 /* Function responsible for updating the exposed area.
113 * It must do an events request to the lttvwindow API to ask for this update.
114 * Note : this function cannot clear the background, because it may
115 * erase drawing already present (SAFETY).
116 */
117 void drawing_data_request(Drawing_t *drawing,
118 gint x, gint y,
119 gint width,
120 gint height)
121 {
122 if(width < 0) return ;
123 if(height < 0) return ;
124
125
126 Tab *tab = drawing->control_flow_data->tab;
127 TimeWindow time_window =
128 lttvwindow_get_time_window(tab);
129
130 ControlFlowData *control_flow_data = drawing->control_flow_data;
131 // (ControlFlowData*)g_object_get_data(
132 // G_OBJECT(drawing->drawing_area), "control_flow_data");
133
134 LttTime start, time_end;
135 LttTime window_end = time_window.end_time;
136
137 g_debug("req : window start_time : %lu, %lu", time_window.start_time.tv_sec,
138 time_window.start_time.tv_nsec);
139
140 g_debug("req : window time width : %lu, %lu", time_window.time_width.tv_sec,
141 time_window.time_width.tv_nsec);
142
143 g_debug("req : window_end : %lu, %lu", window_end.tv_sec,
144 window_end.tv_nsec);
145
146 g_debug("x is : %i, x+width is : %i", x, x+width);
147
148 convert_pixels_to_time(drawing->width, x,
149 time_window,
150 &start);
151
152 convert_pixels_to_time(drawing->width, x+width,
153 time_window,
154 &time_end);
155 time_end = ltt_time_add(time_end, ltt_time_one); // because main window
156 // doesn't deliver end time.
157
158 lttvwindow_events_request_remove_all(tab,
159 control_flow_data);
160
161 {
162 /* find the tracehooks */
163 LttvTracesetContext *tsc = lttvwindow_get_traceset_context(tab);
164
165 LttvTraceset *traceset = tsc->ts;
166
167 guint i, k, l, nb_trace;
168
169 LttvTraceState *ts;
170
171 LttvTracefileState *tfs;
172
173 GArray *hooks;
174
175 LttvTraceHook *hook;
176
177 LttvTraceHook *th;
178
179 guint ret;
180 gint first_after;
181
182 nb_trace = lttv_traceset_number(traceset);
183 // FIXME (fixed) : eventually request for more traces
184 for(i = 0 ; i < nb_trace ; i++) {
185 EventsRequest *events_request = g_new(EventsRequest, 1);
186 // Create the hooks
187 //LttvHooks *event = lttv_hooks_new();
188 LttvHooksById *event_by_id = lttv_hooks_by_id_new();
189 LttvHooks *before_chunk_traceset = lttv_hooks_new();
190 LttvHooks *after_chunk_traceset = lttv_hooks_new();
191 LttvHooks *before_request_hook = lttv_hooks_new();
192 LttvHooks *after_request_hook = lttv_hooks_new();
193
194 lttv_hooks_add(before_chunk_traceset,
195 before_chunk,
196 events_request,
197 LTTV_PRIO_DEFAULT);
198
199 lttv_hooks_add(after_chunk_traceset,
200 after_chunk,
201 events_request,
202 LTTV_PRIO_DEFAULT);
203
204 lttv_hooks_add(before_request_hook,
205 before_request,
206 events_request,
207 LTTV_PRIO_DEFAULT);
208
209 lttv_hooks_add(after_request_hook,
210 after_request,
211 events_request,
212 LTTV_PRIO_DEFAULT);
213
214
215 ts = (LttvTraceState *)tsc->traces[i];
216
217 /* Find the eventtype id for the following events and register the
218 associated by id hooks. */
219
220 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 18);
221
222 /* before hooks */
223
224 lttv_trace_find_hook(ts->parent.t,
225 LTT_FACILITY_KERNEL_ARCH,
226 LTT_EVENT_SYSCALL_ENTRY,
227 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID),
228 before_execmode_hook,
229 events_request,
230 &hooks);
231
232 lttv_trace_find_hook(ts->parent.t,
233 LTT_FACILITY_KERNEL_ARCH,
234 LTT_EVENT_SYSCALL_EXIT,
235 NULL,
236 before_execmode_hook,
237 events_request,
238 &hooks);
239
240 lttv_trace_find_hook(ts->parent.t,
241 LTT_FACILITY_KERNEL_ARCH,
242 LTT_EVENT_TRAP_ENTRY,
243 FIELD_ARRAY(LTT_FIELD_TRAP_ID),
244 before_execmode_hook,
245 events_request,
246 &hooks);
247
248 lttv_trace_find_hook(ts->parent.t,
249 LTT_FACILITY_KERNEL_ARCH,
250 LTT_EVENT_TRAP_EXIT,
251 NULL,
252 before_execmode_hook,
253 events_request,
254 &hooks);
255
256 lttv_trace_find_hook(ts->parent.t,
257 LTT_FACILITY_KERNEL,
258 LTT_EVENT_IRQ_ENTRY,
259 FIELD_ARRAY(LTT_FIELD_IRQ_ID),
260 before_execmode_hook,
261 events_request,
262 &hooks);
263
264 lttv_trace_find_hook(ts->parent.t,
265 LTT_FACILITY_KERNEL,
266 LTT_EVENT_IRQ_EXIT,
267 NULL,
268 before_execmode_hook,
269 events_request,
270 &hooks);
271
272 lttv_trace_find_hook(ts->parent.t,
273 LTT_FACILITY_KERNEL,
274 LTT_EVENT_SOFT_IRQ_ENTRY,
275 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID),
276 before_execmode_hook,
277 events_request,
278 &hooks);
279
280 lttv_trace_find_hook(ts->parent.t,
281 LTT_FACILITY_KERNEL,
282 LTT_EVENT_SOFT_IRQ_EXIT,
283 NULL,
284 before_execmode_hook,
285 events_request,
286 &hooks);
287
288
289 lttv_trace_find_hook(ts->parent.t,
290 LTT_FACILITY_KERNEL,
291 LTT_EVENT_SCHED_SCHEDULE,
292 FIELD_ARRAY(LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID, LTT_FIELD_PREV_STATE),
293 before_schedchange_hook,
294 events_request,
295 &hooks);
296
297 lttv_trace_find_hook(ts->parent.t,
298 LTT_FACILITY_KERNEL,
299 LTT_EVENT_PROCESS_EXIT,
300 FIELD_ARRAY(LTT_FIELD_PID),
301 before_process_exit_hook,
302 events_request,
303 &hooks);
304
305 lttv_trace_find_hook(ts->parent.t,
306 LTT_FACILITY_KERNEL,
307 LTT_EVENT_PROCESS_FREE,
308 FIELD_ARRAY(LTT_FIELD_PID),
309 before_process_release_hook,
310 events_request,
311 &hooks);
312
313 lttv_trace_find_hook(ts->parent.t,
314 LTT_FACILITY_LIST,
315 LTT_EVENT_STATEDUMP_END,
316 NULL,
317 before_statedump_end,
318 events_request,
319 &hooks);
320
321 /* After hooks */
322 first_after = hooks->len;
323
324 lttv_trace_find_hook(ts->parent.t,
325 LTT_FACILITY_KERNEL,
326 LTT_EVENT_SCHED_SCHEDULE,
327 FIELD_ARRAY(LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID, LTT_FIELD_PREV_STATE),
328 after_schedchange_hook,
329 events_request,
330 &hooks);
331
332 lttv_trace_find_hook(ts->parent.t,
333 LTT_FACILITY_KERNEL,
334 LTT_EVENT_PROCESS_FORK,
335 FIELD_ARRAY(LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID),
336 after_process_fork_hook,
337 events_request,
338 &hooks);
339
340 lttv_trace_find_hook(ts->parent.t,
341 LTT_FACILITY_KERNEL,
342 LTT_EVENT_PROCESS_EXIT,
343 FIELD_ARRAY(LTT_FIELD_PID),
344 after_process_exit_hook,
345 events_request,
346 &hooks);
347
348 lttv_trace_find_hook(ts->parent.t,
349 LTT_FACILITY_FS,
350 LTT_EVENT_EXEC,
351 NULL,
352 after_fs_exec_hook,
353 events_request,
354 &hooks);
355
356 lttv_trace_find_hook(ts->parent.t,
357 LTT_FACILITY_USER_GENERIC,
358 LTT_EVENT_THREAD_BRAND,
359 FIELD_ARRAY(LTT_FIELD_NAME),
360 after_user_generic_thread_brand_hook,
361 events_request,
362 &hooks);
363
364 lttv_trace_find_hook(ts->parent.t,
365 LTT_FACILITY_LIST,
366 LTT_EVENT_PROCESS_STATE,
367 FIELD_ARRAY(LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME),
368 after_event_enum_process_hook,
369 events_request,
370 &hooks);
371
372
373 /* Add these hooks to each event_by_id hooks list */
374 /* add before */
375 for(k = 0 ; k < first_after ; k++) {
376 th = &g_array_index(hooks, LttvTraceHook, k);
377 lttv_hooks_add(lttv_hooks_by_id_find(event_by_id, th->id),
378 th->h,
379 th,
380 LTTV_PRIO_STATE-5);
381 }
382
383 /* add after */
384 for(k = first_after ; k < hooks->len ; k++) {
385 th = &g_array_index(hooks, LttvTraceHook, k);
386 lttv_hooks_add(lttv_hooks_by_id_find(event_by_id, th->id),
387 th->h,
388 th,
389 LTTV_PRIO_STATE+5);
390 }
391
392 events_request->hooks = hooks;
393
394 // Fill the events request
395 events_request->owner = control_flow_data;
396 events_request->viewer_data = control_flow_data;
397 events_request->servicing = FALSE;
398 events_request->start_time = start;
399 events_request->start_position = NULL;
400 events_request->stop_flag = FALSE;
401 events_request->end_time = time_end;
402 events_request->num_events = G_MAXUINT;
403 events_request->end_position = NULL;
404 events_request->trace = i; //fixed /* FIXME */
405 events_request->before_chunk_traceset = before_chunk_traceset;
406 events_request->before_chunk_trace = NULL;
407 events_request->before_chunk_tracefile = NULL;
408 events_request->event = NULL;
409 events_request->event_by_id = event_by_id;
410 events_request->after_chunk_tracefile = NULL;
411 events_request->after_chunk_trace = NULL;
412 events_request->after_chunk_traceset = after_chunk_traceset;
413 events_request->before_request = before_request_hook;
414 events_request->after_request = after_request_hook;
415
416 g_debug("req : start : %lu, %lu", start.tv_sec,
417 start.tv_nsec);
418
419 g_debug("req : end : %lu, %lu", time_end.tv_sec,
420 time_end.tv_nsec);
421
422 lttvwindow_events_request(tab, events_request);
423 }
424 }
425 }
426
427
428 static void set_last_start(gpointer key, gpointer value, gpointer user_data)
429 {
430 ProcessInfo *process_info = (ProcessInfo*)key;
431 HashedProcessData *hashed_process_data = (HashedProcessData*)value;
432 guint x = (guint)user_data;
433
434 hashed_process_data->x.over = x;
435 hashed_process_data->x.over_used = FALSE;
436 hashed_process_data->x.over_marked = FALSE;
437 hashed_process_data->x.middle = x;
438 hashed_process_data->x.middle_used = FALSE;
439 hashed_process_data->x.middle_marked = FALSE;
440 hashed_process_data->x.under = x;
441 hashed_process_data->x.under_used = FALSE;
442 hashed_process_data->x.under_marked = FALSE;
443 hashed_process_data->next_good_time = ltt_time_zero;
444
445 return;
446 }
447
448 void drawing_data_request_begin(EventsRequest *events_request, LttvTracesetState *tss)
449 {
450 g_debug("Begin of data request");
451 ControlFlowData *cfd = events_request->viewer_data;
452 LttvTracesetContext *tsc = LTTV_TRACESET_CONTEXT(tss);
453 TimeWindow time_window =
454 lttvwindow_get_time_window(cfd->tab);
455
456 guint width = cfd->drawing->width;
457 guint x=0;
458
459 cfd->drawing->last_start = events_request->start_time;
460
461 convert_time_to_pixels(
462 time_window,
463 events_request->start_time,
464 width,
465 &x);
466
467 g_hash_table_foreach(cfd->process_list->process_hash, set_last_start,
468 (gpointer)x);
469
470 }
471
472 void drawing_chunk_begin(EventsRequest *events_request, LttvTracesetState *tss)
473 {
474 g_debug("Begin of chunk");
475 ControlFlowData *cfd = events_request->viewer_data;
476 LttvTracesetContext *tsc = &tss->parent.parent;
477 //LttTime current_time = lttv_traceset_context_get_current_tfc(tsc)->timestamp;
478 guint i;
479 LttvTraceset *traceset = tsc->ts;
480 guint nb_trace = lttv_traceset_number(traceset);
481
482 if(!cfd->process_list->current_hash_data) {
483 cfd->process_list->current_hash_data = g_new(HashedProcessData**,nb_trace);
484 for(i = 0 ; i < nb_trace ; i++) {
485 guint num_cpu = ltt_trace_get_num_cpu(tss->parent.traces[i]->t);
486 cfd->process_list->current_hash_data[i] = g_new(HashedProcessData*,num_cpu);
487 memset(cfd->process_list->current_hash_data[i], 0,
488 sizeof(HashedProcessData*)*num_cpu);
489 }
490 }
491 //cfd->drawing->last_start = LTT_TIME_MIN(current_time,
492 // events_request->end_time);
493 }
494
495
496 void drawing_request_expose(EventsRequest *events_request,
497 LttvTracesetState *tss,
498 LttTime end_time)
499 {
500 gint x, width;
501 guint x_end;
502
503 ControlFlowData *cfd = events_request->viewer_data;
504 LttvTracesetContext *tsc = (LttvTracesetContext*)tss;
505 Drawing_t *drawing = cfd->drawing;
506
507 TimeWindow time_window =
508 lttvwindow_get_time_window(cfd->tab);
509
510 g_debug("request expose");
511
512 convert_time_to_pixels(
513 time_window,
514 end_time,
515 drawing->width,
516 &x_end);
517 x = drawing->damage_begin;
518
519 width = x_end - x;
520
521 drawing->damage_begin = x+width;
522
523 // FIXME ?
524 gtk_widget_queue_draw_area ( drawing->drawing_area,
525 x, 0,
526 width, drawing->drawing_area->allocation.height);
527
528 /* Update directly when scrolling */
529 gdk_window_process_updates(drawing->drawing_area->window,
530 TRUE);
531 }
532
533
534 /* Callbacks */
535
536
537 /* Create a new backing pixmap of the appropriate size */
538 /* As the scaling will always change, it's of no use to copy old
539 * pixmap.
540 *
541 * Only change the size if width changes. The height is specified and changed
542 * when process ID are added or removed from the process list.
543 */
544 static gboolean
545 configure_event( GtkWidget *widget, GdkEventConfigure *event,
546 gpointer user_data)
547 {
548 Drawing_t *drawing = (Drawing_t*)user_data;
549
550
551 /* First, get the new time interval of the main window */
552 /* we assume (see documentation) that the main window
553 * has updated the time interval before this configure gets
554 * executed.
555 */
556 //lttvwindow_get_time_window(drawing->control_flow_data->mw,
557 // &drawing->control_flow_data->time_window);
558
559 /* New pixmap, size of the configure event */
560 //GdkPixmap *pixmap = gdk_pixmap_new(widget->window,
561 // widget->allocation.width + SAFETY,
562 // widget->allocation.height + SAFETY,
563 // -1);
564
565 if(widget->allocation.width != drawing->width) {
566 g_debug("drawing configure event");
567 g_debug("New alloc draw size : %i by %i",widget->allocation.width,
568 widget->allocation.height);
569
570 drawing->width = widget->allocation.width;
571
572 if(drawing->alloc_width < widget->allocation.width) {
573 //if(drawing->pixmap)
574 // gdk_pixmap_unref(drawing->pixmap);
575
576 //drawing->pixmap = gdk_pixmap_new(widget->window,
577 // drawing->width + SAFETY + EXTRA_ALLOC,
578 // drawing->height + EXTRA_ALLOC,
579 // -1);
580 drawing->alloc_width = drawing->width + SAFETY + EXTRA_ALLOC;
581 drawing->alloc_height = drawing->height + EXTRA_ALLOC;
582 update_pixmap_size(drawing->control_flow_data->process_list,
583 drawing->alloc_width);
584 update_index_to_pixmap(drawing->control_flow_data->process_list);
585 }
586 //drawing->height = widget->allocation.height;
587
588 //ProcessList_get_height
589 // (GuiControlFlow_get_process_list(drawing->control_flow_data)),
590
591
592 // Clear the image
593 //gdk_draw_rectangle (drawing->pixmap,
594 // widget->style->black_gc,
595 // TRUE,
596 // 0, 0,
597 // drawing->width+SAFETY,
598 // drawing->height);
599
600 //g_info("init data request");
601
602
603 /* Initial data request */
604 /* no, do initial data request in the expose event */
605 // Do not need to ask for data of 1 pixel : not synchronized with
606 // main window time at this moment.
607 //drawing_data_request(drawing, &drawing->pixmap, 0, 0,
608 // widget->allocation.width,
609 // widget->allocation.height);
610
611 //drawing->width = widget->allocation.width;
612 //drawing->height = widget->allocation.height;
613
614 drawing->damage_begin = 0;
615 drawing->damage_end = widget->allocation.width;
616
617 if((widget->allocation.width != 1 &&
618 widget->allocation.height != 1)
619 && drawing->damage_begin < drawing->damage_end)
620 {
621
622 rectangle_pixmap (drawing->control_flow_data->process_list,
623 drawing->drawing_area->style->black_gc,
624 TRUE,
625 0, 0,
626 drawing->alloc_width, // do not overlap
627 -1);
628
629
630 drawing_data_request(drawing,
631 drawing->damage_begin,
632 0,
633 drawing->damage_end - drawing->damage_begin,
634 drawing->height);
635 }
636 }
637 return TRUE;
638 }
639
640
641 /* Redraw the screen from the backing pixmap */
642 static gboolean
643 expose_event( GtkWidget *widget, GdkEventExpose *event, gpointer user_data )
644 {
645 Drawing_t *drawing = (Drawing_t*)user_data;
646
647 ControlFlowData *control_flow_data =
648 (ControlFlowData*)g_object_get_data(
649 G_OBJECT(widget),
650 "control_flow_data");
651 #if 0
652 if(unlikely(drawing->gc == NULL)) {
653 drawing->gc = gdk_gc_new(drawing->drawing_area->window);
654 gdk_gc_copy(drawing->gc, drawing->drawing_area->style->black_gc);
655 }
656 #endif //0
657 TimeWindow time_window =
658 lttvwindow_get_time_window(control_flow_data->tab);
659 LttTime current_time =
660 lttvwindow_get_current_time(control_flow_data->tab);
661
662 guint cursor_x=0;
663
664 LttTime window_end = time_window.end_time;
665
666 /* update the screen from the pixmap buffer */
667 #if 0
668 gdk_draw_pixmap(widget->window,
669 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
670 drawing->pixmap,
671 event->area.x, event->area.y,
672 event->area.x, event->area.y,
673 event->area.width, event->area.height);
674 #endif //0
675 drawing->height = processlist_get_height(control_flow_data->process_list);
676 #if 0
677 copy_pixmap_to_screen(control_flow_data->process_list,
678 widget->window,
679 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
680 event->area.x, event->area.y,
681 event->area.width, event->area.height);
682 #endif //0
683 copy_pixmap_to_screen(control_flow_data->process_list,
684 widget->window,
685 drawing->gc,
686 event->area.x, event->area.y,
687 event->area.width, event->area.height);
688
689
690 /* Erase the dotted lines left.. */
691 if(widget->allocation.height > drawing->height)
692 {
693 gdk_draw_rectangle (widget->window,
694 drawing->drawing_area->style->black_gc,
695 TRUE,
696 event->area.x, drawing->height,
697 event->area.width, // do not overlap
698 widget->allocation.height - drawing->height);
699 }
700 if(ltt_time_compare(time_window.start_time, current_time) <= 0 &&
701 ltt_time_compare(window_end, current_time) >= 0)
702 {
703 /* Draw the dotted lines */
704 convert_time_to_pixels(
705 time_window,
706 current_time,
707 drawing->width,
708 &cursor_x);
709
710 #if 0
711 if(drawing->dotted_gc == NULL) {
712
713 drawing->dotted_gc = gdk_gc_new(drawing->drawing_area->window);
714 gdk_gc_copy(drawing->dotted_gc, widget->style->white_gc);
715
716 gint8 dash_list[] = { 1, 2 };
717 gdk_gc_set_line_attributes(drawing->dotted_gc,
718 1,
719 GDK_LINE_ON_OFF_DASH,
720 GDK_CAP_BUTT,
721 GDK_JOIN_MITER);
722 gdk_gc_set_dashes(drawing->dotted_gc,
723 0,
724 dash_list,
725 2);
726 }
727 #endif //0
728 gint height_tot = MAX(widget->allocation.height, drawing->height);
729 gdk_draw_line(widget->window,
730 drawing->dotted_gc,
731 cursor_x, 0,
732 cursor_x, height_tot);
733 }
734 return FALSE;
735 }
736
737 static gboolean
738 after_expose_event( GtkWidget *widget, GdkEventExpose *event, gpointer user_data )
739 {
740 //g_assert(0);
741 g_debug("AFTER EXPOSE");
742
743 return FALSE;
744
745
746 }
747
748 #if 0
749 void
750 tree_row_activated(GtkTreeModel *treemodel,
751 GtkTreePath *arg1,
752 GtkTreeViewColumn *arg2,
753 gpointer user_data)
754 {
755 ControlFlowData *cfd = (ControlFlowData*)user_data;
756 Drawing_t *drawing = cfd->drawing;
757 GtkTreeView *treeview = cfd->process_list->process_list_widget;
758 gint *path_indices;
759 gint height;
760
761 path_indices = gtk_tree_path_get_indices (arg1);
762
763 height = get_cell_height(cfd->process_list,
764 GTK_TREE_VIEW(treeview));
765 drawing->horizontal_sel = height * path_indices[0];
766 g_critical("new hor sel : %i", drawing->horizontal_sel);
767 }
768 #endif //0
769
770 /* mouse click */
771 static gboolean
772 button_press_event( GtkWidget *widget, GdkEventButton *event, gpointer user_data )
773 {
774 ControlFlowData *control_flow_data =
775 (ControlFlowData*)g_object_get_data(
776 G_OBJECT(widget),
777 "control_flow_data");
778 Drawing_t *drawing = control_flow_data->drawing;
779 TimeWindow time_window =
780 lttvwindow_get_time_window(control_flow_data->tab);
781
782 g_debug("click");
783 if(event->button == 1)
784 {
785 LttTime time;
786
787 /* left mouse button click */
788 g_debug("x click is : %f", event->x);
789
790 convert_pixels_to_time(drawing->width, (guint)event->x,
791 time_window,
792 &time);
793
794 lttvwindow_report_current_time(control_flow_data->tab, time);
795
796 }
797
798 return FALSE;
799 }
800
801 static gboolean
802 scrollbar_size_allocate(GtkWidget *widget,
803 GtkAllocation *allocation,
804 gpointer user_data)
805 {
806 Drawing_t *drawing = (Drawing_t*)user_data;
807
808 gtk_widget_set_size_request(drawing->padding, allocation->width, -1);
809 //gtk_widget_queue_resize(drawing->padding);
810 //gtk_widget_queue_resize(drawing->ruler);
811 gtk_container_check_resize(GTK_CONTAINER(drawing->ruler_hbox));
812 return 0;
813 }
814
815
816
817 Drawing_t *drawing_construct(ControlFlowData *control_flow_data)
818 {
819 Drawing_t *drawing = g_new(Drawing_t, 1);
820
821 drawing->control_flow_data = control_flow_data;
822
823 drawing->vbox = gtk_vbox_new(FALSE, 1);
824
825
826 drawing->ruler_hbox = gtk_hbox_new(FALSE, 1);
827 drawing->ruler = gtk_drawing_area_new ();
828 //gtk_widget_set_size_request(drawing->ruler, -1, 27);
829
830 drawing->padding = gtk_drawing_area_new ();
831 //gtk_widget_set_size_request(drawing->padding, -1, 27);
832 gtk_box_pack_start(GTK_BOX(drawing->ruler_hbox), drawing->ruler,
833 TRUE, TRUE, 0);
834 gtk_box_pack_end(GTK_BOX(drawing->ruler_hbox), drawing->padding,
835 FALSE, FALSE, 0);
836
837
838
839 drawing->drawing_area = gtk_drawing_area_new ();
840
841 drawing->gc = NULL;
842
843 drawing->hbox = gtk_hbox_new(FALSE, 1);
844 drawing->viewport = gtk_viewport_new(NULL, control_flow_data->v_adjust);
845 drawing->scrollbar = gtk_vscrollbar_new(control_flow_data->v_adjust);
846 gtk_box_pack_start(GTK_BOX(drawing->hbox), drawing->viewport,
847 TRUE, TRUE, 0);
848 gtk_box_pack_end(GTK_BOX(drawing->hbox), drawing->scrollbar,
849 FALSE, FALSE, 0);
850
851 //drawing->scrolled_window =
852 // gtk_scrolled_window_new (NULL,
853 // control_flow_data->v_adjust);
854
855 //gtk_scrolled_window_set_policy(
856 // GTK_SCROLLED_WINDOW(drawing->scrolled_window),
857 // GTK_POLICY_NEVER,
858 // GTK_POLICY_AUTOMATIC);
859
860 gtk_container_add(GTK_CONTAINER(drawing->viewport),
861 drawing->drawing_area);
862 //gtk_scrolled_window_add_with_viewport(
863 // GTK_SCROLLED_WINDOW(drawing->scrolled_window),
864 // drawing->drawing_area);
865
866 gtk_box_pack_start(GTK_BOX(drawing->vbox), drawing->ruler_hbox,
867 FALSE, FALSE, 0);
868 gtk_box_pack_end(GTK_BOX(drawing->vbox), drawing->hbox,
869 TRUE, TRUE, 0);
870
871 drawing->pango_layout =
872 gtk_widget_create_pango_layout(drawing->drawing_area, NULL);
873
874 drawing->height = 1;
875 drawing->width = 1;
876 drawing->depth = 0;
877 drawing->alloc_height = 1;
878 drawing->alloc_width = 1;
879
880 drawing->damage_begin = 0;
881 drawing->damage_end = 0;
882 drawing->horizontal_sel = -1;
883
884 //gtk_widget_set_size_request(drawing->drawing_area->window, 50, 50);
885 g_object_set_data_full(
886 G_OBJECT(drawing->drawing_area),
887 "Link_drawing_Data",
888 drawing,
889 (GDestroyNotify)drawing_destroy);
890
891 g_object_set_data(
892 G_OBJECT(drawing->ruler),
893 "drawing",
894 drawing);
895
896
897 //gtk_widget_modify_bg( drawing->drawing_area,
898 // GTK_STATE_NORMAL,
899 // &CF_Colors[BLACK]);
900
901 //gdk_window_get_geometry(drawing->drawing_area->window,
902 // NULL, NULL,
903 // &(drawing->width),
904 // &(drawing->height),
905 // -1);
906
907 //drawing->pixmap = gdk_pixmap_new(
908 // drawing->drawing_area->window,
909 // drawing->width,
910 // drawing->height,
911 // drawing->depth);
912
913 //drawing->pixmap = NULL;
914
915 // drawing->pixmap = gdk_pixmap_new(drawing->drawing_area->window,
916 // drawing->drawing_area->allocation.width,
917 // drawing->drawing_area->allocation.height,
918 // -1);
919
920 g_signal_connect (G_OBJECT(drawing->drawing_area),
921 "configure_event",
922 G_CALLBACK (configure_event),
923 (gpointer)drawing);
924
925 g_signal_connect (G_OBJECT(drawing->ruler),
926 "expose_event",
927 G_CALLBACK(expose_ruler),
928 (gpointer)drawing);
929
930 gtk_widget_add_events(drawing->ruler, GDK_POINTER_MOTION_MASK);
931
932 g_signal_connect (G_OBJECT(drawing->ruler),
933 "motion-notify-event",
934 G_CALLBACK(motion_notify_ruler),
935 (gpointer)drawing);
936
937
938 g_signal_connect (G_OBJECT(drawing->scrollbar),
939 "size-allocate",
940 G_CALLBACK(scrollbar_size_allocate),
941 (gpointer)drawing);
942
943
944
945 g_signal_connect (G_OBJECT(drawing->drawing_area),
946 "expose_event",
947 G_CALLBACK (expose_event),
948 (gpointer)drawing);
949
950 g_signal_connect_after (G_OBJECT(drawing->drawing_area),
951 "expose_event",
952 G_CALLBACK (after_expose_event),
953 (gpointer)drawing);
954
955 g_signal_connect (G_OBJECT(drawing->drawing_area),
956 "button-press-event",
957 G_CALLBACK (button_press_event),
958 (gpointer)drawing);
959
960
961 gtk_widget_show(drawing->ruler);
962 gtk_widget_show(drawing->padding);
963 gtk_widget_show(drawing->ruler_hbox);
964
965 gtk_widget_show(drawing->drawing_area);
966 //gtk_widget_show(drawing->scrolled_window);
967 gtk_widget_show(drawing->viewport);
968 gtk_widget_show(drawing->scrollbar);
969 gtk_widget_show(drawing->hbox);
970
971 /* Allocate the colors */
972 GdkColormap* colormap = gdk_colormap_get_system();
973 gboolean success[NUM_COLORS];
974 gdk_colormap_alloc_colors(colormap, drawing_colors, NUM_COLORS, FALSE,
975 TRUE, success);
976
977 drawing->gc =
978 gdk_gc_new(GDK_DRAWABLE(main_window_get_widget(control_flow_data->tab)->window));
979 drawing->dotted_gc =
980 gdk_gc_new(GDK_DRAWABLE(main_window_get_widget(control_flow_data->tab)->window));
981
982 gdk_gc_copy(drawing->gc,
983 main_window_get_widget(control_flow_data->tab)->style->black_gc);
984 gdk_gc_copy(drawing->dotted_gc,
985 main_window_get_widget(control_flow_data->tab)->style->white_gc);
986
987 gint8 dash_list[] = { 1, 2 };
988 gdk_gc_set_line_attributes(drawing->dotted_gc,
989 1,
990 GDK_LINE_ON_OFF_DASH,
991 GDK_CAP_BUTT,
992 GDK_JOIN_MITER);
993 gdk_gc_set_dashes(drawing->dotted_gc,
994 0,
995 dash_list,
996 2);
997
998 drawing->ruler_gc_butt =
999 gdk_gc_new(GDK_DRAWABLE(main_window_get_widget(control_flow_data->tab)->window));
1000 gdk_gc_copy(drawing->ruler_gc_butt,
1001 main_window_get_widget(control_flow_data->tab)->style->black_gc);
1002 drawing->ruler_gc_round =
1003 gdk_gc_new(GDK_DRAWABLE(main_window_get_widget(control_flow_data->tab)->window));
1004 gdk_gc_copy(drawing->ruler_gc_round,
1005 main_window_get_widget(control_flow_data->tab)->style->black_gc);
1006
1007
1008 gdk_gc_set_line_attributes(drawing->ruler_gc_butt,
1009 2,
1010 GDK_LINE_SOLID,
1011 GDK_CAP_BUTT,
1012 GDK_JOIN_MITER);
1013
1014 gdk_gc_set_line_attributes(drawing->ruler_gc_round,
1015 2,
1016 GDK_LINE_SOLID,
1017 GDK_CAP_ROUND,
1018 GDK_JOIN_ROUND);
1019
1020
1021 return drawing;
1022 }
1023
1024 void drawing_destroy(Drawing_t *drawing)
1025 {
1026 g_info("drawing_destroy %p", drawing);
1027
1028 /* Free the colors */
1029 GdkColormap* colormap = gdk_colormap_get_system();
1030
1031 gdk_colormap_free_colors(colormap, drawing_colors, NUM_COLORS);
1032
1033
1034
1035 // Do not unref here, Drawing_t destroyed by it's widget.
1036 //g_object_unref( G_OBJECT(drawing->drawing_area));
1037 if(drawing->gc != NULL)
1038 gdk_gc_unref(drawing->gc);
1039
1040 g_object_unref(drawing->pango_layout);
1041 if(drawing->dotted_gc != NULL) gdk_gc_unref(drawing->dotted_gc);
1042 if(drawing->ruler_gc_butt != NULL) gdk_gc_unref(drawing->ruler_gc_butt);
1043 if(drawing->ruler_gc_round != NULL) gdk_gc_unref(drawing->ruler_gc_round);
1044
1045 g_free(drawing);
1046 g_info("drawing_destroy end");
1047 }
1048
1049 GtkWidget *drawing_get_drawing_area(Drawing_t *drawing)
1050 {
1051 return drawing->drawing_area;
1052 }
1053
1054 GtkWidget *drawing_get_widget(Drawing_t *drawing)
1055 {
1056 return drawing->vbox;
1057 }
1058
1059 void drawing_draw_line( Drawing_t *drawing,
1060 GdkPixmap *pixmap,
1061 guint x1, guint y1,
1062 guint x2, guint y2,
1063 GdkGC *GC)
1064 {
1065 gdk_draw_line (pixmap,
1066 GC,
1067 x1, y1, x2, y2);
1068 }
1069
1070 void drawing_clear(Drawing_t *drawing)
1071 {
1072 //if (drawing->pixmap)
1073 // gdk_pixmap_unref(drawing->pixmap);
1074 ControlFlowData *cfd = drawing->control_flow_data;
1075
1076
1077 rectangle_pixmap(cfd->process_list,
1078 drawing->drawing_area->style->black_gc,
1079 TRUE,
1080 0, 0,
1081 drawing->alloc_width, // do not overlap
1082 -1);
1083
1084 //drawing->height = 1;
1085 /* Allocate a new pixmap with new height */
1086 //drawing->pixmap = gdk_pixmap_new(drawing->drawing_area->window,
1087 // drawing->width + SAFETY + EXTRA_ALLOC,
1088 // drawing->height + EXTRA_ALLOC,
1089 // -1);
1090 //drawing->alloc_width = drawing->width + SAFETY + EXTRA_ALLOC;
1091 //drawing->alloc_height = drawing->height + EXTRA_ALLOC;
1092
1093 //gtk_widget_set_size_request(drawing->drawing_area,
1094 // -1,
1095 // drawing->height);
1096 //gtk_widget_queue_resize_no_redraw(drawing->drawing_area);
1097
1098 /* ask for the buffer to be redrawn */
1099 gtk_widget_queue_draw ( drawing->drawing_area);
1100 }
1101
1102 #if 0
1103 /* Insert a square corresponding to a new process in the list */
1104 /* Applies to whole drawing->width */
1105 void drawing_insert_square(Drawing_t *drawing,
1106 guint y,
1107 guint height)
1108 {
1109 //GdkRectangle update_rect;
1110 gboolean reallocate = FALSE;
1111 GdkPixmap *new_pixmap;
1112
1113 /* Allocate a new pixmap with new height */
1114 if(drawing->alloc_height < drawing->height + height) {
1115
1116 new_pixmap = gdk_pixmap_new(drawing->drawing_area->window,
1117 drawing->width + SAFETY + EXTRA_ALLOC,
1118 drawing->height + height + EXTRA_ALLOC,
1119 -1);
1120 drawing->alloc_width = drawing->width + SAFETY + EXTRA_ALLOC;
1121 drawing->alloc_height = drawing->height + height + EXTRA_ALLOC;
1122 reallocate = TRUE;
1123
1124 /* Copy the high region */
1125 gdk_draw_pixmap (new_pixmap,
1126 drawing->drawing_area->style->black_gc,
1127 drawing->pixmap,
1128 0, 0,
1129 0, 0,
1130 drawing->width + SAFETY, y);
1131
1132 } else {
1133 new_pixmap = drawing->pixmap;
1134 }
1135
1136 //GdkPixmap *pixmap = gdk_pixmap_new(drawing->drawing_area->window,
1137 // drawing->width + SAFETY,
1138 // drawing->height + height,
1139 // -1);
1140
1141 /* add an empty square */
1142 gdk_draw_rectangle (new_pixmap,
1143 drawing->drawing_area->style->black_gc,
1144 TRUE,
1145 0, y,
1146 drawing->width + SAFETY, // do not overlap
1147 height);
1148
1149 /* copy the bottom of the region */
1150 gdk_draw_pixmap (new_pixmap,
1151 drawing->drawing_area->style->black_gc,
1152 drawing->pixmap,
1153 0, y,
1154 0, y + height,
1155 drawing->width+SAFETY, drawing->height - y);
1156
1157
1158 if(reallocate && likely(drawing->pixmap)) {
1159 gdk_pixmap_unref(drawing->pixmap);
1160 drawing->pixmap = new_pixmap;
1161 }
1162
1163 if(unlikely(drawing->height==1)) drawing->height = height;
1164 else drawing->height += height;
1165
1166 gtk_widget_set_size_request(drawing->drawing_area,
1167 -1,
1168 drawing->height);
1169 gtk_widget_queue_resize_no_redraw(drawing->drawing_area);
1170
1171 /* ask for the buffer to be redrawn */
1172 gtk_widget_queue_draw_area ( drawing->drawing_area,
1173 0, y,
1174 drawing->width, drawing->height-y);
1175 }
1176
1177
1178 /* Remove a square corresponding to a removed process in the list */
1179 void drawing_remove_square(Drawing_t *drawing,
1180 guint y,
1181 guint height)
1182 {
1183 GdkPixmap *pixmap;
1184
1185 if(unlikely((guint)drawing->height == height)) {
1186 //pixmap = gdk_pixmap_new(
1187 // drawing->drawing_area->window,
1188 // drawing->width + SAFETY,
1189 // 1,
1190 // -1);
1191 pixmap = drawing->pixmap;
1192 drawing->height=1;
1193 } else {
1194 /* Allocate a new pixmap with new height */
1195 //pixmap = gdk_pixmap_new(
1196 // drawing->drawing_area->window,
1197 // drawing->width + SAFETY,
1198 // drawing->height - height,
1199 // -1);
1200 /* Keep the same preallocated pixmap */
1201 pixmap = drawing->pixmap;
1202
1203 /* Copy the high region */
1204 gdk_draw_pixmap (pixmap,
1205 drawing->drawing_area->style->black_gc,
1206 drawing->pixmap,
1207 0, 0,
1208 0, 0,
1209 drawing->width + SAFETY, y);
1210
1211 /* Copy up the bottom of the region */
1212 gdk_draw_pixmap (pixmap,
1213 drawing->drawing_area->style->black_gc,
1214 drawing->pixmap,
1215 0, y + height,
1216 0, y,
1217 drawing->width, drawing->height - y - height);
1218
1219 drawing->height-=height;
1220 }
1221
1222 //if(likely(drawing->pixmap))
1223 // gdk_pixmap_unref(drawing->pixmap);
1224
1225 //drawing->pixmap = pixmap;
1226
1227 gtk_widget_set_size_request(drawing->drawing_area,
1228 -1,
1229 drawing->height);
1230 gtk_widget_queue_resize_no_redraw(drawing->drawing_area);
1231 /* ask for the buffer to be redrawn */
1232 gtk_widget_queue_draw_area ( drawing->drawing_area,
1233 0, y,
1234 drawing->width, MAX(drawing->height-y, 1));
1235 }
1236 #endif //0
1237
1238 void drawing_update_ruler(Drawing_t *drawing, TimeWindow *time_window)
1239 {
1240 GtkRequisition req;
1241 GdkRectangle rect;
1242
1243 req.width = drawing->ruler->allocation.width;
1244 req.height = drawing->ruler->allocation.height;
1245
1246
1247 rect.x = 0;
1248 rect.y = 0;
1249 rect.width = req.width;
1250 rect.height = req.height;
1251
1252 gtk_widget_queue_draw(drawing->ruler);
1253 //gtk_widget_draw( drawing->ruler, &rect);
1254 }
1255
1256 /* Redraw the ruler */
1257 static gboolean
1258 expose_ruler( GtkWidget *widget, GdkEventExpose *event, gpointer user_data )
1259 {
1260 Drawing_t *drawing = (Drawing_t*)user_data;
1261 TimeWindow time_window = lttvwindow_get_time_window(drawing->control_flow_data->tab);
1262 gchar text[255];
1263
1264 PangoContext *context;
1265 PangoLayout *layout;
1266 PangoFontDescription *FontDesc;
1267 PangoRectangle ink_rect;
1268 gint global_width=0;
1269 GdkColor foreground = { 0, 0, 0, 0 };
1270 GdkColor background = { 0, 0xffff, 0xffff, 0xffff };
1271
1272 LttTime window_end = time_window.end_time;
1273 LttTime half_width =
1274 ltt_time_div(time_window.time_width,2.0);
1275 LttTime window_middle =
1276 ltt_time_add(half_width,
1277 time_window.start_time);
1278 g_debug("ruler expose event");
1279
1280 gdk_draw_rectangle (drawing->ruler->window,
1281 drawing->ruler->style->white_gc,
1282 TRUE,
1283 event->area.x, event->area.y,
1284 event->area.width,
1285 event->area.height);
1286
1287 gdk_draw_line (drawing->ruler->window,
1288 drawing->ruler_gc_butt,
1289 event->area.x, 1,
1290 event->area.x + event->area.width, 1);
1291
1292
1293 snprintf(text, 255, "%lus\n%luns",
1294 time_window.start_time.tv_sec,
1295 time_window.start_time.tv_nsec);
1296
1297 layout = gtk_widget_create_pango_layout(drawing->drawing_area, NULL);
1298
1299 context = pango_layout_get_context(layout);
1300 FontDesc = pango_context_get_font_description(context);
1301
1302 pango_font_description_set_size(FontDesc, 6*PANGO_SCALE);
1303 pango_layout_context_changed(layout);
1304
1305 pango_layout_set_text(layout, text, -1);
1306 pango_layout_get_pixel_extents(layout, &ink_rect, NULL);
1307 global_width += ink_rect.width;
1308
1309 gdk_draw_layout_with_colors(drawing->ruler->window,
1310 drawing->ruler_gc_butt,
1311 0,
1312 6,
1313 layout, &foreground, &background);
1314
1315 gdk_draw_line (drawing->ruler->window,
1316 drawing->ruler_gc_round,
1317 1, 1,
1318 1, 7);
1319
1320
1321 snprintf(text, 255, "%lus\n%luns", window_end.tv_sec,
1322 window_end.tv_nsec);
1323
1324 pango_layout_set_text(layout, text, -1);
1325 pango_layout_get_pixel_extents(layout, &ink_rect, NULL);
1326 global_width += ink_rect.width;
1327
1328 if(global_width <= drawing->ruler->allocation.width)
1329 {
1330 gdk_draw_layout_with_colors(drawing->ruler->window,
1331 drawing->ruler_gc_butt,
1332 drawing->ruler->allocation.width - ink_rect.width,
1333 6,
1334 layout, &foreground, &background);
1335
1336 gdk_draw_line (drawing->ruler->window,
1337 drawing->ruler_gc_butt,
1338 drawing->ruler->allocation.width-1, 1,
1339 drawing->ruler->allocation.width-1, 7);
1340 }
1341
1342
1343 snprintf(text, 255, "%lus\n%luns", window_middle.tv_sec,
1344 window_middle.tv_nsec);
1345
1346 pango_layout_set_text(layout, text, -1);
1347 pango_layout_get_pixel_extents(layout, &ink_rect, NULL);
1348 global_width += ink_rect.width;
1349
1350 if(global_width <= drawing->ruler->allocation.width)
1351 {
1352 gdk_draw_layout_with_colors(drawing->ruler->window,
1353 drawing->ruler_gc_butt,
1354 (drawing->ruler->allocation.width - ink_rect.width)/2,
1355 6,
1356 layout, &foreground, &background);
1357
1358 gdk_draw_line (drawing->ruler->window,
1359 drawing->ruler_gc_butt,
1360 drawing->ruler->allocation.width/2, 1,
1361 drawing->ruler->allocation.width/2, 7);
1362
1363
1364
1365
1366 }
1367
1368 g_object_unref(layout);
1369
1370 return FALSE;
1371 }
1372
1373
1374 /* notify mouse on ruler */
1375 static gboolean
1376 motion_notify_ruler(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
1377 {
1378 //g_debug("motion");
1379 //eventually follow mouse and show time here
1380 return 0;
1381 }
This page took 0.101234 seconds and 4 git commands to generate.