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