evolution-3.6.4/libgnomecanvas/gnome-canvas.c

Location Tool Test ID Function Issue
gnome-canvas.c:677:29 clang-analyzer Access to field 'need_repick' results in a dereference of a null pointer (loaded from field 'canvas')
gnome-canvas.c:677:29 clang-analyzer Access to field 'need_repick' results in a dereference of a null pointer (loaded from field 'canvas')
gnome-canvas.c:1585:11 clang-analyzer The left operand of '<' is a garbage value
gnome-canvas.c:1585:11 clang-analyzer The right operand of '<' is a garbage value
gnome-canvas.c:1585:11 clang-analyzer The right operand of '<' is a garbage value
gnome-canvas.c:1585:11 clang-analyzer The left operand of '<' is a garbage value
gnome-canvas.c:1598:6 clang-analyzer Assigned value is garbage or undefined
gnome-canvas.c:1598:6 clang-analyzer Assigned value is garbage or undefined
gnome-canvas.c:2910:2 clang-analyzer Function call argument is an uninitialized value
gnome-canvas.c:2910:2 clang-analyzer Function call argument is an uninitialized value
gnome-canvas.c:2912:2 clang-analyzer Function call argument is an uninitialized value
gnome-canvas.c:2912:2 clang-analyzer Function call argument is an uninitialized value
gnome-canvas.c:3030:9 clang-analyzer Function call argument is an uninitialized value
gnome-canvas.c:3030:9 clang-analyzer Function call argument is an uninitialized value
   1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: 8; c-basic-offset: 8 -*- */
   2 /*
   3  * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation
   4  * All rights reserved.
   5  *
   6  * This file is part of the Gnome Library.
   7  *
   8  * The Gnome Library is free software; you can redistribute it and/or
   9  * modify it under the terms of the GNU Library General Public License as
  10  * published by the Free Software Foundation; either version 2 of the
  11  * License, or (at your option) any later version.
  12  *
  13  * The Gnome Library is distributed in the hope that it will be useful,
  14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16  * Library General Public License for more details.
  17  *
  18  * You should have received a copy of the GNU Library General Public
  19  * License along with the Gnome Library; see the file COPYING.LIB.  If not,
  20  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  21  * Boston, MA 02111-1307, USA.
  22  */
  23 /*
  24   @NOTATION@
  25  */
  26 /*
  27  * GnomeCanvas widget - Tk-like canvas widget for Gnome
  28  *
  29  * GnomeCanvas is basically a port of the Tk toolkit's most excellent canvas
  30  * widget.  Tk is copyrighted by the Regents of the University of California,
  31  * Sun Microsystems, and other parties.
  32  *
  33  *
  34  * Authors: Federico Mena <federico@nuclecu.unam.mx>
  35  *          Raph Levien <raph@gimp.org>
  36  */
  37 
  38 /*
  39  * TO-DO list for the canvas:
  40  *
  41  * - Allow to specify whether GnomeCanvasImage sizes are in units or pixels
  42  *   (scale or don't scale).
  43  *
  44  * - Implement a flag for gnome_canvas_item_reparent() that tells the function
  45  *   to keep the item visually in the same place, that is, to keep it in the
  46  *   same place with respect to the canvas origin.
  47  *
  48  * - GC put functions for items.
  49  *
  50  * - Widget item (finish it).
  51  *
  52  * - GList *
  53  *   gnome_canvas_gimme_all_items_contained_in_this_area (GnomeCanvas *canvas,
  54  *                                                        Rectangle area);
  55  *
  56  * - Retrofit all the primitive items with microtile support.
  57  *
  58  * - Curve support for line item.
  59  *
  60  * - Arc item (Havoc has it; to be integrated in GnomeCanvasEllipse).
  61  *
  62  * - Sane font handling API.
  63  *
  64  * - Get_arg methods for items:
  65  *   - How to fetch the outline width and know whether it is in pixels or units?
  66  */
  67 
  68 /*
  69  * Raph's TODO list for the antialiased canvas integration:
  70  *
  71  * - ::point() method for text item not accurate when affine transformed.
  72  *
  73  * - Clip rectangle not implemented in aa renderer for text item.
  74  *
  75  * - Clip paths only partially implemented.
  76  *
  77  * - Add more image loading techniques to work around imlib deficiencies.
  78  */
  79 
  80 #ifdef HAVE_CONFIG_H
  81 #include <config.h>
  82 #endif
  83 
  84 #include <math.h>
  85 #include <string.h>
  86 #include <stdio.h>
  87 #include <gdk/gdkprivate.h>
  88 #include <gtk/gtk.h>
  89 #include <cairo-gobject.h>
  90 #include "gailcanvas.h"
  91 #include "gnome-canvas.h"
  92 #include "gnome-canvas-i18n.h"
  93 #include "gnome-canvas-util.h"
  94 
  95 /* We must run our idle update handler *before* GDK wants to redraw. */
  96 #define CANVAS_IDLE_PRIORITY (GDK_PRIORITY_REDRAW - 5)
  97 
  98 static void gnome_canvas_request_update (GnomeCanvas      *canvas);
  99 static void group_add                   (GnomeCanvasGroup *group,
 100 					 GnomeCanvasItem  *item);
 101 static void group_remove                (GnomeCanvasGroup *group,
 102 					 GnomeCanvasItem  *item);
 103 static void add_idle                    (GnomeCanvas      *canvas);
 104 
 105 /*** GnomeCanvasItem ***/
 106 
 107 /* Some convenience stuff */
 108 #define GCI_UPDATE_MASK \
 109 	(GNOME_CANVAS_UPDATE_REQUESTED | \
 110 	 GNOME_CANVAS_UPDATE_AFFINE | \
 111 	 GNOME_CANVAS_UPDATE_CLIP | \
 112 	 GNOME_CANVAS_UPDATE_VISIBILITY)
 113 #define GCI_EPSILON 1e-18
 114 #define GCI_PRINT_MATRIX(s,a) \
 115 	g_print ("%s %g %g %g %g %g %g\n", \
 116 	s, (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5])
 117 
 118 enum {
 119 	ITEM_PROP_0,
 120 	ITEM_PROP_PARENT
 121 };
 122 
 123 enum {
 124 	ITEM_EVENT,
 125 	ITEM_LAST_SIGNAL
 126 };
 127 
 128 static gint  emit_event                       (GnomeCanvas *canvas, GdkEvent *event);
 129 
 130 static guint item_signals[ITEM_LAST_SIGNAL];
 131 
 132 G_DEFINE_TYPE (
 133 	GnomeCanvasItem,
 134 	gnome_canvas_item,
 135 	G_TYPE_INITIALLY_UNOWNED)
 136 
 137 /* Object initialization function for GnomeCanvasItem */
 138 static void
 139 gnome_canvas_item_init (GnomeCanvasItem *item)
 140 {
 141 	item->flags |= GNOME_CANVAS_ITEM_VISIBLE;
 142 
 143 	cairo_matrix_init_identity (&item->matrix);
 144 }
 145 
 146 /**
 147  * gnome_canvas_item_new:
 148  * @parent: The parent group for the new item.
 149  * @type: The object type of the item.
 150  * @first_arg_name: A list of object argument name/value pairs, NULL-terminated,
 151  * used to configure the item.  For example, "fill_color", "black",
 152  * "width_units", 5.0, NULL.
 153  * @Varargs:
 154  *
 155  * Creates a new canvas item with @parent as its parent group.  The item is
 156  * created at the top of its parent's stack, and starts up as visible.  The item
 157  * is of the specified @type, for example, it can be
 158  * gnome_canvas_rect_get_type().  The list of object arguments/value pairs is
 159  * used to configure the item. If you need to pass construct time parameters, you
 160  * should use g_object_new() to pass the parameters and
 161  * gnome_canvas_item_construct() to set up the canvas item.
 162  *
 163  * Return value: The newly-created item.
 164  **/
 165 GnomeCanvasItem *
 166 gnome_canvas_item_new (GnomeCanvasGroup *parent,
 167                        GType type,
 168                        const gchar *first_arg_name, ...)
 169 {
 170 	GnomeCanvasItem *item;
 171 	va_list args;
 172 
 173 	g_return_val_if_fail (GNOME_IS_CANVAS_GROUP (parent), NULL);
 174 	g_return_val_if_fail (g_type_is_a (type, gnome_canvas_item_get_type ()), NULL);
 175 
 176 	item = GNOME_CANVAS_ITEM (g_object_new (type, NULL));
 177 
 178 	va_start (args, first_arg_name);
 179 	gnome_canvas_item_construct (item, parent, first_arg_name, args);
 180 	va_end (args);
 181 
 182 	return item;
 183 }
 184 
 185 /* Performs post-creation operations on a canvas item (adding it to its parent
 186  * group, etc.)
 187  */
 188 static void
 189 item_post_create_setup (GnomeCanvasItem *item)
 190 {
 191 	group_add (GNOME_CANVAS_GROUP (item->parent), item);
 192 
 193 	gnome_canvas_request_redraw (
 194 		item->canvas, item->x1, item->y1, item->x2 + 1, item->y2 + 1);
 195 	item->canvas->need_repick = TRUE;
 196 }
 197 
 198 /* Set_property handler for canvas items */
 199 static void
 200 gnome_canvas_item_set_property (GObject *gobject,
 201                                 guint property_id,
 202                                 const GValue *value,
 203                                 GParamSpec *pspec)
 204 {
 205 	GnomeCanvasItem *item;
 206 
 207 	g_return_if_fail (GNOME_IS_CANVAS_ITEM (gobject));
 208 
 209 	item = GNOME_CANVAS_ITEM (gobject);
 210 
 211 	switch (property_id) {
 212 	case ITEM_PROP_PARENT:
 213 		if (item->parent != NULL) {
 214 		    g_warning ("Cannot set `parent' argument after item has "
 215 			       "already been constructed.");
 216 		} else if (g_value_get_object (value)) {
 217 			item->parent = GNOME_CANVAS_ITEM (g_value_get_object (value));
 218 			item->canvas = item->parent->canvas;
 219 			item_post_create_setup (item);
 220 		}
 221 		break;
 222 	default:
 223 		G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
 224 		break;
 225 	}
 226 }
 227 
 228 /* Get_property handler for canvas items */
 229 static void
 230 gnome_canvas_item_get_property (GObject *gobject,
 231                                 guint property_id,
 232                                 GValue *value,
 233                                 GParamSpec *pspec)
 234 {
 235 	GnomeCanvasItem *item;
 236 
 237 	g_return_if_fail (GNOME_IS_CANVAS_ITEM (gobject));
 238 
 239 	item = GNOME_CANVAS_ITEM (gobject);
 240 
 241 	switch (property_id) {
 242 	case ITEM_PROP_PARENT:
 243 		g_value_set_object (value, item->parent);
 244 		break;
 245 
 246 	default:
 247 		G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
 248 		break;
 249 	}
 250 }
 251 
 252 /**
 253  * gnome_canvas_item_construct:
 254  * @item: An unconstructed canvas item.
 255  * @parent: The parent group for the item.
 256  * @first_arg_name: The name of the first argument for configuring the item.
 257  * @args: The list of arguments used to configure the item.
 258  *
 259  * Constructs a canvas item; meant for use only by item implementations.
 260  **/
 261 void
 262 gnome_canvas_item_construct (GnomeCanvasItem *item,
 263                              GnomeCanvasGroup *parent,
 264                              const gchar *first_arg_name,
 265                              va_list args)
 266 {
 267 	g_return_if_fail (GNOME_IS_CANVAS_GROUP (parent));
 268 	g_return_if_fail (GNOME_IS_CANVAS_ITEM (item));
 269 
 270 	item->parent = GNOME_CANVAS_ITEM (parent);
 271 	item->canvas = item->parent->canvas;
 272 
 273 	g_object_set_valist (G_OBJECT (item), first_arg_name, args);
 274 
 275 	item_post_create_setup (item);
 276 }
 277 
 278 /* If the item is visible, requests a redraw of it. */
 279 static void
 280 redraw_if_visible (GnomeCanvasItem *item)
 281 {
 282 	if (item->flags & GNOME_CANVAS_ITEM_VISIBLE)
 283 		gnome_canvas_request_redraw (
 284 			item->canvas, item->x1, item->y1,
 285 			item->x2 + 1, item->y2 + 1);
 286 }
 287 
 288 /* Standard object dispose function for canvas items */
 289 static void
 290 gnome_canvas_item_dispose (GObject *object)
 291 {
 292 	GnomeCanvasItem *item;
 293 
 294 	g_return_if_fail (GNOME_IS_CANVAS_ITEM (object));
 295 
 296 	item = GNOME_CANVAS_ITEM (object);
 297 
 298 	if (item->canvas)
 299 		redraw_if_visible (item);
 300 
 301 	/* Make the canvas forget about us */
 302 
 303 	if (item->canvas && item == item->canvas->current_item) {
 304 		item->canvas->current_item = NULL;
 305 		item->canvas->need_repick = TRUE;
 306 	}
 307 
 308 	if (item->canvas && item == item->canvas->new_current_item) {
 309 		item->canvas->new_current_item = NULL;
 310 		item->canvas->need_repick = TRUE;
 311 	}
 312 
 313 	if (item->canvas && item == item->canvas->grabbed_item) {
 314 		item->canvas->grabbed_item = NULL;
 315 		gdk_pointer_ungrab (GDK_CURRENT_TIME);
 316 	}
 317 
 318 	if (item->canvas && item == item->canvas->focused_item)
 319 		item->canvas->focused_item = NULL;
 320 
 321 	/* Normal dispose stuff */
 322 
 323 	if (item->flags & GNOME_CANVAS_ITEM_MAPPED)
 324 		(* GNOME_CANVAS_ITEM_GET_CLASS (item)->unmap) (item);
 325 
 326 	if (item->flags & GNOME_CANVAS_ITEM_REALIZED)
 327 		(* GNOME_CANVAS_ITEM_GET_CLASS (item)->unrealize) (item);
 328 
 329 	if (item->parent)
 330 		group_remove (GNOME_CANVAS_GROUP (item->parent), item);
 331 
 332 	if (GNOME_CANVAS_ITEM_GET_CLASS (item)->dispose)
 333 		GNOME_CANVAS_ITEM_GET_CLASS (item)->dispose (item);
 334 
 335 	G_OBJECT_CLASS (gnome_canvas_item_parent_class)->dispose (object);
 336 	/* items should remove any reference to item->canvas after the
 337 	 * first ::dispose */
 338 	item->canvas = NULL;
 339 }
 340 
 341 /* Update handler for canvas items */
 342 static void
 343 gnome_canvas_item_update (GnomeCanvasItem *item,
 344                           const cairo_matrix_t *matrix,
 345                           gint flags)
 346 {
 347 	item->flags &= ~GNOME_CANVAS_ITEM_NEED_UPDATE;
 348 	item->flags &= ~GNOME_CANVAS_ITEM_NEED_AFFINE;
 349 	item->flags &= ~GNOME_CANVAS_ITEM_NEED_CLIP;
 350 	item->flags &= ~GNOME_CANVAS_ITEM_NEED_VIS;
 351 }
 352 
 353 /* Realize handler for canvas items */
 354 static void
 355 gnome_canvas_item_realize (GnomeCanvasItem *item)
 356 {
 357 	item->flags |= GNOME_CANVAS_ITEM_REALIZED;
 358 
 359 	gnome_canvas_item_request_update (item);
 360 }
 361 
 362 /* Unrealize handler for canvas items */
 363 static void
 364 gnome_canvas_item_unrealize (GnomeCanvasItem *item)
 365 {
 366 	item->flags &= ~GNOME_CANVAS_ITEM_REALIZED;
 367 }
 368 
 369 /* Map handler for canvas items */
 370 static void
 371 gnome_canvas_item_map (GnomeCanvasItem *item)
 372 {
 373 	item->flags |= GNOME_CANVAS_ITEM_MAPPED;
 374 }
 375 
 376 /* Unmap handler for canvas items */
 377 static void
 378 gnome_canvas_item_unmap (GnomeCanvasItem *item)
 379 {
 380 	item->flags &= ~GNOME_CANVAS_ITEM_MAPPED;
 381 }
 382 
 383 /* Dispose handler for canvas items */
 384 static void
 385 gnome_canvas_item_dispose_item (GnomeCanvasItem *item)
 386 {
 387 	/* Placeholder so subclasses can safely chain up. */
 388 }
 389 
 390 /*
 391  * This routine invokes the update method of the item
 392  * Please notice, that we take parent to canvas pixel matrix as argument
 393  * unlike virtual method ::update, whose argument is item 2 canvas pixel
 394  * matrix
 395  *
 396  * I will try to force somewhat meaningful naming for affines (Lauris)
 397  * General naming rule is FROM2TO, where FROM and TO are abbreviations
 398  * So p2cpx is Parent2CanvasPixel and i2cpx is Item2CanvasPixel
 399  * I hope that this helps to keep track of what really happens
 400  *
 401  */
 402 
 403 static void
 404 gnome_canvas_item_invoke_update (GnomeCanvasItem *item,
 405                                  const cairo_matrix_t *p2c,
 406                                  gint flags)
 407 {
 408 	gint child_flags;
 409 	cairo_matrix_t i2c;
 410 
 411 	child_flags = flags;
 412 	if (!(item->flags & GNOME_CANVAS_ITEM_VISIBLE))
 413 		child_flags &= ~GNOME_CANVAS_UPDATE_IS_VISIBLE;
 414 
 415 	/* Calculate actual item transformation matrix */
 416 
 417 	cairo_matrix_multiply (&i2c, &item->matrix, p2c);
 418 
 419 	/* apply object flags to child flags */
 420 
 421 	child_flags &= ~GNOME_CANVAS_UPDATE_REQUESTED;
 422 
 423 	if (item->flags & GNOME_CANVAS_ITEM_NEED_UPDATE)
 424 		child_flags |= GNOME_CANVAS_UPDATE_REQUESTED;
 425 
 426 	if (item->flags & GNOME_CANVAS_ITEM_NEED_AFFINE)
 427 		child_flags |= GNOME_CANVAS_UPDATE_AFFINE;
 428 
 429 	if (item->flags & GNOME_CANVAS_ITEM_NEED_CLIP)
 430 		child_flags |= GNOME_CANVAS_UPDATE_CLIP;
 431 
 432 	if (item->flags & GNOME_CANVAS_ITEM_NEED_VIS)
 433 		child_flags |= GNOME_CANVAS_UPDATE_VISIBILITY;
 434 
 435 	if (child_flags & GCI_UPDATE_MASK) {
 436 		if (GNOME_CANVAS_ITEM_GET_CLASS (item)->update)
 437 			GNOME_CANVAS_ITEM_GET_CLASS (item)->update (item, &i2c, child_flags);
 438 	}
 439 }
 440 
 441 /*
 442  * This routine invokes the point method of the item.
 443  * The arguments x, y should be in the parent item local coordinates.
 444  *
 445  * This is potentially evil, as we are relying on matrix inversion (Lauris)
 446  */
 447 
 448 static GnomeCanvasItem *
 449 gnome_canvas_item_invoke_point (GnomeCanvasItem *item,
 450                                 gdouble x,
 451                                 gdouble y,
 452                                 gint cx,
 453                                 gint cy)
 454 {
 455 	cairo_matrix_t inverse;
 456 
 457 	/* Calculate x & y in item local coordinates */
 458 	inverse = item->matrix;
 459 	if (cairo_matrix_invert (&inverse) != CAIRO_STATUS_SUCCESS)
 460 		return NULL;
 461 
 462 	cairo_matrix_transform_point (&inverse, &x, &y);
 463 
 464 	if (GNOME_CANVAS_ITEM_GET_CLASS (item)->point)
 465 		return GNOME_CANVAS_ITEM_GET_CLASS (item)->point (item, x, y, cx, cy);
 466 
 467 	return NULL;
 468 }
 469 
 470 /**
 471  * gnome_canvas_item_set:
 472  * @item: A canvas item.
 473  * @first_arg_name: The list of object argument name/value pairs used to
 474  *                  configure the item.
 475  * @Varargs:
 476  *
 477  * Configures a canvas item.  The arguments in the item are set to the
 478  * specified values, and the item is repainted as appropriate.
 479  **/
 480 void
 481 gnome_canvas_item_set (GnomeCanvasItem *item,
 482                        const gchar *first_arg_name,
 483                        ...)
 484 {
 485 	va_list args;
 486 
 487 	va_start (args, first_arg_name);
 488 	gnome_canvas_item_set_valist (item, first_arg_name, args);
 489 	va_end (args);
 490 }
 491 
 492 /**
 493  * gnome_canvas_item_set_valist:
 494  * @item: A canvas item.
 495  * @first_arg_name: The name of the first argument used to configure the item.
 496  * @args: The list of object argument name/value pairs used to configure the item.
 497  *
 498  * Configures a canvas item.  The arguments in the item are set to the specified
 499  * values, and the item is repainted as appropriate.
 500  **/
 501 void
 502 gnome_canvas_item_set_valist (GnomeCanvasItem *item,
 503                               const gchar *first_arg_name,
 504                               va_list args)
 505 {
 506 	g_return_if_fail (GNOME_IS_CANVAS_ITEM (item));
 507 
 508 	g_object_set_valist (G_OBJECT (item), first_arg_name, args);
 509 
 510 	item->canvas->need_repick = TRUE;
 511 }
 512 
 513 /**
 514  * gnome_canvas_item_transform:
 515  * @item: A canvas item.
 516  * @matrix: An affine transformation matrix.
 517  *
 518  * Combines the specified affine transformation matrix with the item's current
 519  * transformation.
 520  **/
 521 void
 522 gnome_canvas_item_transform (GnomeCanvasItem *item,
 523                              const cairo_matrix_t *matrix)
 524 {
 525 	cairo_matrix_t i2p;
 526 
 527 	g_return_if_fail (GNOME_IS_CANVAS_ITEM (item));
 528 	g_return_if_fail (matrix != NULL);
 529 
 530 	/* Calculate actual item transformation matrix */
 531 	cairo_matrix_multiply (&i2p, matrix, &item->matrix);
 532 
 533 	gnome_canvas_item_set_matrix (item, &i2p);
 534 }
 535 
 536 /**
 537  * gnome_canvas_item_set_matrix:
 538  * @item: A canvas item.
 539  * @matrix: An affine transformation matrix or %NULL for the identity matrix.
 540  *
 541  * Makes the item's affine transformation matrix be equal to the specified
 542  * matrix. NULL is treated as identity.
 543  **/
 544 void
 545 gnome_canvas_item_set_matrix (GnomeCanvasItem *item,
 546                               const cairo_matrix_t *matrix)
 547 {
 548 	g_return_if_fail (GNOME_IS_CANVAS_ITEM (item));
 549 
 550 	if (matrix) {
 551 		item->matrix = *matrix;
 552 	} else {
 553 		cairo_matrix_init_identity (&item->matrix);
 554 	}
 555 
 556 	if (!(item->flags & GNOME_CANVAS_ITEM_NEED_AFFINE)) {
 557 		/* Request update */
 558 		item->flags |= GNOME_CANVAS_ITEM_NEED_AFFINE;
 559 		gnome_canvas_item_request_update (item);
 560 	}
 561 
 562 	item->canvas->need_repick = TRUE;
 563 }
 564 
 565 /**
 566  * gnome_canvas_item_move:
 567  * @item: A canvas item.
 568  * @dx: Horizontal offset.
 569  * @dy: Vertical offset.
 570  *
 571  * Moves a canvas item by creating an affine transformation matrix for
 572  * translation by using the specified values. This happens in item
 573  * local coordinate system, so if you have nontrivial transform, it
 574  * most probably does not do, what you want.
 575  **/
 576 void
 577 gnome_canvas_item_move (GnomeCanvasItem *item,
 578                         gdouble dx,
 579                         gdouble dy)
 580 {
 581 	cairo_matrix_t translate;
 582 
 583 	g_return_if_fail (GNOME_IS_CANVAS_ITEM (item));
 584 
 585 	cairo_matrix_init_translate (&translate, dx, dy);
 586 
 587 	gnome_canvas_item_transform (item, &translate);
 588 }
 589 
 590 /* Convenience function to reorder items in a group's child list.  This puts the
 591  * specified link after the "before" link. Returns TRUE if the list was changed.
 592  */
 593 static gboolean
 594 put_item_after (GList *link,
 595                 GList *before)
 596 {
 597 	GnomeCanvasGroup *parent;
 598 	GList *old_before, *old_after;
 599 	GList *after;
 600 
 601 	parent = GNOME_CANVAS_GROUP (GNOME_CANVAS_ITEM (link->data)->parent);
 602 
 603 	if (before)
 604 		after = before->next;
 605 	else
 606 		after = parent->item_list;
 607 
 608 	if (before == link || after == link)
 609 		return FALSE;
 610 
 611 	/* Unlink */
 612 
 613 	old_before = link->prev;
 614 	old_after = link->next;
 615 
 616 	if (old_before)
 617 		old_before->next = old_after;
 618 	else
 619 		parent->item_list = old_after;
 620 
 621 	if (old_after)
 622 		old_after->prev = old_before;
 623 	else
 624 		parent->item_list_end = old_before;
 625 
 626 	/* Relink */
 627 
 628 	link->prev = before;
 629 	if (before)
 630 		before->next = link;
 631 	else
 632 		parent->item_list = link;
 633 
 634 	link->next = after;
 635 	if (after)
 636 		after->prev = link;
 637 	else
 638 		parent->item_list_end = link;
 639 
 640 	return TRUE;
 641 }
 642 
 643 /**
 644  * gnome_canvas_item_raise:
 645  * @item: A canvas item.
 646  * @positions: Number of steps to raise the item.
 647  *
 648  * Raises the item in its parent's stack by the specified number of positions.
 649  * If the number of positions is greater than the distance to the top of the
 650  * stack, then the item is put at the top.
 651  **/
 652 void
 653 gnome_canvas_item_raise (GnomeCanvasItem *item,
 654                          gint positions)
 655 {
 656 	GList *link, *before;
 657 	GnomeCanvasGroup *parent;
 658 
 659 	g_return_if_fail (GNOME_IS_CANVAS_ITEM (item));
 660 	g_return_if_fail (positions >= 0);
 661 
 662 	if (!item->parent || positions == 0)
 663 		return;
 664 
 665 	parent = GNOME_CANVAS_GROUP (item->parent);
 666 	link = g_list_find (parent->item_list, item);
 667 	g_return_if_fail (link != NULL);
 668 
 669 	for (before = link; positions && before; positions--)
 670 		before = before->next;
 671 
 672 	if (!before)
 673 		before = parent->item_list_end;
 674 
 675 	if (put_item_after (link, before)) {
 676 		redraw_if_visible (item);
 677 		item->canvas->need_repick = TRUE;
Access to field 'need_repick' results in a dereference of a null pointer (loaded from field 'canvas')
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

Access to field 'need_repick' results in a dereference of a null pointer (loaded from field 'canvas')
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

678 } 679 } 680 681 /** 682 * gnome_canvas_item_lower: 683 * @item: A canvas item. 684 * @positions: Number of steps to lower the item. 685 * 686 * Lowers the item in its parent's stack by the specified number of positions. 687 * If the number of positions is greater than the distance to the bottom of the 688 * stack, then the item is put at the bottom. 689 **/ 690 void 691 gnome_canvas_item_lower (GnomeCanvasItem *item, 692 gint positions) 693 { 694 GList *link, *before; 695 GnomeCanvasGroup *parent; 696 697 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); 698 g_return_if_fail (positions >= 1); 699 700 if (!item->parent || positions == 0) 701 return; 702 703 parent = GNOME_CANVAS_GROUP (item->parent); 704 link = g_list_find (parent->item_list, item); 705 g_return_if_fail (link != NULL); 706 707 if (link->prev) 708 for (before = link->prev; positions && before; positions--) 709 before = before->prev; 710 else 711 before = NULL; 712 713 if (put_item_after (link, before)) { 714 redraw_if_visible (item); 715 item->canvas->need_repick = TRUE; 716 } 717 } 718 719 /** 720 * gnome_canvas_item_raise_to_top: 721 * @item: A canvas item. 722 * 723 * Raises an item to the top of its parent's stack. 724 **/ 725 void 726 gnome_canvas_item_raise_to_top (GnomeCanvasItem *item) 727 { 728 GList *link; 729 GnomeCanvasGroup *parent; 730 731 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); 732 733 if (!item->parent) 734 return; 735 736 parent = GNOME_CANVAS_GROUP (item->parent); 737 link = g_list_find (parent->item_list, item); 738 g_return_if_fail (link != NULL); 739 740 if (put_item_after (link, parent->item_list_end)) { 741 redraw_if_visible (item); 742 item->canvas->need_repick = TRUE; 743 } 744 } 745 746 /** 747 * gnome_canvas_item_lower_to_bottom: 748 * @item: A canvas item. 749 * 750 * Lowers an item to the bottom of its parent's stack. 751 **/ 752 void 753 gnome_canvas_item_lower_to_bottom (GnomeCanvasItem *item) 754 { 755 GList *link; 756 GnomeCanvasGroup *parent; 757 758 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); 759 760 if (!item->parent) 761 return; 762 763 parent = GNOME_CANVAS_GROUP (item->parent); 764 link = g_list_find (parent->item_list, item); 765 g_return_if_fail (link != NULL); 766 767 if (put_item_after (link, NULL)) { 768 redraw_if_visible (item); 769 item->canvas->need_repick = TRUE; 770 } 771 } 772 773 /** 774 * gnome_canvas_item_show: 775 * @item: A canvas item. 776 * 777 * Shows a canvas item. If the item was already shown, then no action is taken. 778 **/ 779 void 780 gnome_canvas_item_show (GnomeCanvasItem *item) 781 { 782 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); 783 784 if (!(item->flags & GNOME_CANVAS_ITEM_VISIBLE)) { 785 item->flags |= GNOME_CANVAS_ITEM_VISIBLE; 786 gnome_canvas_request_redraw ( 787 item->canvas, item->x1, item->y1, 788 item->x2 + 1, item->y2 + 1); 789 item->canvas->need_repick = TRUE; 790 } 791 } 792 793 /** 794 * gnome_canvas_item_hide: 795 * @item: A canvas item. 796 * 797 * Hides a canvas item. If the item was already hidden, then no action is 798 * taken. 799 **/ 800 void 801 gnome_canvas_item_hide (GnomeCanvasItem *item) 802 { 803 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); 804 805 if (item->flags & GNOME_CANVAS_ITEM_VISIBLE) { 806 item->flags &= ~GNOME_CANVAS_ITEM_VISIBLE; 807 gnome_canvas_request_redraw ( 808 item->canvas, item->x1, item->y1, 809 item->x2 + 1, item->y2 + 1); 810 item->canvas->need_repick = TRUE; 811 } 812 } 813 814 /** 815 * gnome_canvas_item_grab: 816 * @item: A canvas item. 817 * @event_mask: Mask of events that will be sent to this item. 818 * @cursor: If non-NULL, the cursor that will be used while the grab is active. 819 * @etime: The timestamp required for grabbing the mouse, or GDK_CURRENT_TIME. 820 * 821 * Specifies that all events that match the specified event mask should be sent 822 * to the specified item, and also grabs the mouse by calling 823 * gdk_pointer_grab(). The event mask is also used when grabbing the pointer. 824 * If @cursor is not NULL, then that cursor is used while the grab is active. 825 * The @etime parameter is the timestamp required for grabbing the mouse. 826 * 827 * Return value: If an item was already grabbed, it returns 828 * %GDK_GRAB_ALREADY_GRABBED. If the specified item was hidden by calling 829 * gnome_canvas_item_hide(), then it returns %GDK_GRAB_NOT_VIEWABLE. Else, 830 * it returns the result of calling gdk_pointer_grab(). 831 **/ 832 gint 833 gnome_canvas_item_grab (GnomeCanvasItem *item, 834 guint event_mask, 835 GdkCursor *cursor, 836 guint32 etime) 837 { 838 GtkLayout *layout; 839 GdkWindow *bin_window; 840 gint retval; 841 842 g_return_val_if_fail ( 843 GNOME_IS_CANVAS_ITEM (item), GDK_GRAB_NOT_VIEWABLE); 844 g_return_val_if_fail ( 845 gtk_widget_get_mapped (GTK_WIDGET (item->canvas)), 846 GDK_GRAB_NOT_VIEWABLE); 847 848 if (item->canvas->grabbed_item) 849 return GDK_GRAB_ALREADY_GRABBED; 850 851 if (!(item->flags & GNOME_CANVAS_ITEM_VISIBLE)) 852 return GDK_GRAB_NOT_VIEWABLE; 853 854 layout = GTK_LAYOUT (item->canvas); 855 bin_window = gtk_layout_get_bin_window (layout); 856 857 retval = gdk_pointer_grab ( 858 bin_window, FALSE, event_mask, 859 NULL, cursor, etime); 860 861 if (retval != GDK_GRAB_SUCCESS) 862 return retval; 863 864 item->canvas->grabbed_item = item; 865 item->canvas->grabbed_event_mask = event_mask; 866 item->canvas->current_item = item; /* So that events go to the grabbed item */ 867 868 return retval; 869 } 870 871 /** 872 * gnome_canvas_item_ungrab: 873 * @item: A canvas item that holds a grab. 874 * @etime: The timestamp for ungrabbing the mouse. 875 * 876 * Ungrabs the item, which must have been grabbed in the canvas, and ungrabs the 877 * mouse. 878 **/ 879 void 880 gnome_canvas_item_ungrab (GnomeCanvasItem *item, 881 guint32 etime) 882 { 883 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); 884 885 if (item->canvas->grabbed_item != item) 886 return; 887 888 item->canvas->grabbed_item = NULL; 889 890 gdk_pointer_ungrab (etime); 891 } 892 893 void 894 gnome_canvas_item_i2w_matrix (GnomeCanvasItem *item, 895 cairo_matrix_t *matrix) 896 { 897 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); 898 g_return_if_fail (matrix != NULL); 899 900 cairo_matrix_init_identity (matrix); 901 902 while (item) { 903 cairo_matrix_multiply (matrix, matrix, &item->matrix); 904 905 item = item->parent; 906 } 907 } 908 909 void 910 gnome_canvas_item_w2i_matrix (GnomeCanvasItem *item, 911 cairo_matrix_t *matrix) 912 { 913 cairo_status_t status; 914 915 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); 916 g_return_if_fail (matrix != NULL); 917 918 gnome_canvas_item_i2w_matrix (item, matrix); 919 status = cairo_matrix_invert (matrix); 920 g_return_if_fail (status == CAIRO_STATUS_SUCCESS); 921 } 922 923 /** 924 * gnome_canvas_item_w2i: 925 * @item: A canvas item. 926 * @x: X coordinate to convert (input/output value). 927 * @y: Y coordinate to convert (input/output value). 928 * 929 * Converts a coordinate pair from world coordinates to item-relative 930 * coordinates. 931 **/ 932 void 933 gnome_canvas_item_w2i (GnomeCanvasItem *item, 934 gdouble *x, 935 gdouble *y) 936 { 937 cairo_matrix_t matrix; 938 939 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); 940 g_return_if_fail (x != NULL); 941 g_return_if_fail (y != NULL); 942 943 gnome_canvas_item_w2i_matrix (item, &matrix); 944 cairo_matrix_transform_point (&matrix, x, y); 945 } 946 947 /** 948 * gnome_canvas_item_i2w: 949 * @item: A canvas item. 950 * @x: X coordinate to convert (input/output value). 951 * @y: Y coordinate to convert (input/output value). 952 * 953 * Converts a coordinate pair from item-relative coordinates to world 954 * coordinates. 955 **/ 956 void 957 gnome_canvas_item_i2w (GnomeCanvasItem *item, 958 gdouble *x, 959 gdouble *y) 960 { 961 cairo_matrix_t matrix; 962 963 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); 964 g_return_if_fail (x != NULL); 965 g_return_if_fail (y != NULL); 966 967 gnome_canvas_item_i2w_matrix (item, &matrix); 968 cairo_matrix_transform_point (&matrix, x, y); 969 } 970 971 /** 972 * gnome_canvas_item_i2c_matrix: 973 * @item: A canvas item. 974 * @matrix: Matrix to take the resulting transformation matrix (return value). 975 * 976 * Gets the affine transform that converts from item-relative coordinates to 977 * canvas pixel coordinates. 978 **/ 979 void 980 gnome_canvas_item_i2c_matrix (GnomeCanvasItem *item, 981 cairo_matrix_t *matrix) 982 { 983 cairo_matrix_t i2w, w2c; 984 985 gnome_canvas_item_i2w_matrix (item, &i2w); 986 gnome_canvas_w2c_matrix (item->canvas, &w2c); 987 cairo_matrix_multiply (matrix, &i2w, &w2c); 988 } 989 990 /* Returns whether the item is an inferior of or is equal to the parent. */ 991 static gint 992 is_descendant (GnomeCanvasItem *item, 993 GnomeCanvasItem *parent) 994 { 995 for (; item; item = item->parent) 996 if (item == parent) 997 return TRUE; 998 999 return FALSE; 1000 } 1001 1002 /** 1003 * gnome_canvas_item_reparent: 1004 * @item: A canvas item. 1005 * @new_group: A canvas group. 1006 * 1007 * Changes the parent of the specified item to be the new group. The item keeps 1008 * its group-relative coordinates as for its old parent, so the item may change 1009 * its absolute position within the canvas. 1010 **/ 1011 void 1012 gnome_canvas_item_reparent (GnomeCanvasItem *item, 1013 GnomeCanvasGroup *new_group) 1014 { 1015 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); 1016 g_return_if_fail (GNOME_IS_CANVAS_GROUP (new_group)); 1017 1018 /* Both items need to be in the same canvas */ 1019 g_return_if_fail (item->canvas == GNOME_CANVAS_ITEM (new_group)->canvas); 1020 1021 /* The group cannot be an inferior of the item or be the item itself -- 1022 * this also takes care of the case where the item is the root item of 1023 * the canvas. */ 1024 g_return_if_fail (!is_descendant (GNOME_CANVAS_ITEM (new_group), item)); 1025 1026 /* Everything is ok, now actually reparent the item */ 1027 1028 g_object_ref (item); /* protect it from the unref in group_remove */ 1029 1030 redraw_if_visible (item); 1031 1032 group_remove (GNOME_CANVAS_GROUP (item->parent), item); 1033 item->parent = GNOME_CANVAS_ITEM (new_group); 1034 group_add (new_group, item); 1035 1036 /* Redraw and repick */ 1037 1038 redraw_if_visible (item); 1039 item->canvas->need_repick = TRUE; 1040 1041 g_object_unref (item); 1042 } 1043 1044 /** 1045 * gnome_canvas_item_grab_focus: 1046 * @item: A canvas item. 1047 * 1048 * Makes the specified item take the keyboard focus, so all keyboard events will 1049 * be sent to it. If the canvas widget itself did not have the focus, it grabs 1050 * it as well. 1051 **/ 1052 void 1053 gnome_canvas_item_grab_focus (GnomeCanvasItem *item) 1054 { 1055 GnomeCanvasItem *focused_item; 1056 GdkEvent ev; 1057 1058 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); 1059 g_return_if_fail (gtk_widget_get_can_focus (GTK_WIDGET (item->canvas))); 1060 1061 focused_item = item->canvas->focused_item; 1062 1063 if (focused_item) { 1064 GtkLayout *layout; 1065 GdkWindow *bin_window; 1066 1067 layout = GTK_LAYOUT (item->canvas); 1068 bin_window = gtk_layout_get_bin_window (layout); 1069 1070 ev.focus_change.type = GDK_FOCUS_CHANGE; 1071 ev.focus_change.window = bin_window; 1072 ev.focus_change.send_event = FALSE; 1073 ev.focus_change.in = FALSE; 1074 1075 emit_event (item->canvas, &ev); 1076 } 1077 1078 item->canvas->focused_item = item; 1079 gtk_widget_grab_focus (GTK_WIDGET (item->canvas)); 1080 1081 if (focused_item) { 1082 GtkLayout *layout; 1083 GdkWindow *bin_window; 1084 1085 layout = GTK_LAYOUT (item->canvas); 1086 bin_window = gtk_layout_get_bin_window (layout); 1087 1088 ev.focus_change.type = GDK_FOCUS_CHANGE; 1089 ev.focus_change.window = bin_window; 1090 ev.focus_change.send_event = FALSE; 1091 ev.focus_change.in = TRUE; 1092 1093 emit_event (item->canvas, &ev); 1094 } 1095 } 1096 1097 /** 1098 * gnome_canvas_item_get_bounds: 1099 * @item: A canvas item. 1100 * @x1: Leftmost edge of the bounding box (return value). 1101 * @y1: Upper edge of the bounding box (return value). 1102 * @x2: Rightmost edge of the bounding box (return value). 1103 * @y2: Lower edge of the bounding box (return value). 1104 * 1105 * Queries the bounding box of a canvas item. The bounds are returned in the 1106 * coordinate system of the item's parent. 1107 **/ 1108 void 1109 gnome_canvas_item_get_bounds (GnomeCanvasItem *item, 1110 gdouble *x1, 1111 gdouble *y1, 1112 gdouble *x2, 1113 gdouble *y2) 1114 { 1115 gdouble tx1, ty1, tx2, ty2; 1116 1117 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); 1118 1119 tx1 = ty1 = tx2 = ty2 = 0.0; 1120 1121 /* Get the item's bounds in its coordinate system */ 1122 1123 if (GNOME_CANVAS_ITEM_GET_CLASS (item)->bounds) 1124 GNOME_CANVAS_ITEM_GET_CLASS (item)->bounds ( 1125 item, &tx1, &ty1, &tx2, &ty2); 1126 1127 /* Make the bounds relative to the item's parent coordinate system */ 1128 gnome_canvas_matrix_transform_rect (&item->matrix, &tx1, &ty1, &tx2, &ty2); 1129 1130 /* Return the values */ 1131 1132 if (x1) 1133 *x1 = tx1; 1134 1135 if (y1) 1136 *y1 = ty1; 1137 1138 if (x2) 1139 *x2 = tx2; 1140 1141 if (y2) 1142 *y2 = ty2; 1143 } 1144 1145 /** 1146 * gnome_canvas_item_request_update 1147 * @item: A canvas item. 1148 * 1149 * To be used only by item implementations. Requests that the canvas queue an 1150 * update for the specified item. 1151 **/ 1152 void 1153 gnome_canvas_item_request_update (GnomeCanvasItem *item) 1154 { 1155 if (item->flags & GNOME_CANVAS_ITEM_NEED_UPDATE) 1156 return; 1157 1158 item->flags |= GNOME_CANVAS_ITEM_NEED_UPDATE; 1159 1160 if (item->parent != NULL) { 1161 /* Recurse up the tree */ 1162 gnome_canvas_item_request_update (item->parent); 1163 } else { 1164 /* Have reached the top of the tree, make 1165 * sure the update call gets scheduled. */ 1166 gnome_canvas_request_update (item->canvas); 1167 } 1168 } 1169 1170 /*** GnomeCanvasGroup ***/ 1171 1172 enum { 1173 GROUP_PROP_0, 1174 GROUP_PROP_X, 1175 GROUP_PROP_Y 1176 }; 1177 1178 static void gnome_canvas_group_set_property (GObject *object, 1179 guint property_id, 1180 const GValue *value, 1181 GParamSpec *pspec); 1182 static void gnome_canvas_group_get_property (GObject *object, 1183 guint property_id, 1184 GValue *value, 1185 GParamSpec *pspec); 1186 1187 static void gnome_canvas_group_dispose (GnomeCanvasItem *object); 1188 1189 static void gnome_canvas_group_update (GnomeCanvasItem *item, 1190 const cairo_matrix_t *matrix, 1191 gint flags); 1192 static void gnome_canvas_group_realize (GnomeCanvasItem *item); 1193 static void gnome_canvas_group_unrealize (GnomeCanvasItem *item); 1194 static void gnome_canvas_group_map (GnomeCanvasItem *item); 1195 static void gnome_canvas_group_unmap (GnomeCanvasItem *item); 1196 static void gnome_canvas_group_draw (GnomeCanvasItem *item, 1197 cairo_t *cr, 1198 gint x, gint y, 1199 gint width, gint height); 1200 static GnomeCanvasItem *gnome_canvas_group_point (GnomeCanvasItem *item, 1201 gdouble x, gdouble y, 1202 gint cx, gint cy); 1203 static void gnome_canvas_group_bounds (GnomeCanvasItem *item, 1204 gdouble *x1, gdouble *y1, 1205 gdouble *x2, gdouble *y2); 1206 1207 G_DEFINE_TYPE ( 1208 GnomeCanvasGroup, 1209 gnome_canvas_group, 1210 GNOME_TYPE_CANVAS_ITEM) 1211 1212 /* Class initialization function for GnomeCanvasGroupClass */ 1213 static void 1214 gnome_canvas_group_class_init (GnomeCanvasGroupClass *class) 1215 { 1216 GObjectClass *object_class; 1217 GnomeCanvasItemClass *item_class; 1218 1219 object_class = (GObjectClass *) class; 1220 item_class = (GnomeCanvasItemClass *) class; 1221 1222 object_class->set_property = gnome_canvas_group_set_property; 1223 object_class->get_property = gnome_canvas_group_get_property; 1224 1225 g_object_class_install_property ( 1226 object_class, 1227 GROUP_PROP_X, 1228 g_param_spec_double ( 1229 "x", 1230 "X", 1231 "X", 1232 -G_MAXDOUBLE, 1233 G_MAXDOUBLE, 1234 0.0, 1235 G_PARAM_READABLE | 1236 G_PARAM_WRITABLE)); 1237 1238 g_object_class_install_property ( 1239 object_class, 1240 GROUP_PROP_Y, 1241 g_param_spec_double ( 1242 "y", 1243 "Y", 1244 "Y", 1245 -G_MAXDOUBLE, 1246 G_MAXDOUBLE, 1247 0.0, 1248 G_PARAM_READABLE | 1249 G_PARAM_WRITABLE)); 1250 1251 item_class->dispose = gnome_canvas_group_dispose; 1252 item_class->update = gnome_canvas_group_update; 1253 item_class->realize = gnome_canvas_group_realize; 1254 item_class->unrealize = gnome_canvas_group_unrealize; 1255 item_class->map = gnome_canvas_group_map; 1256 item_class->unmap = gnome_canvas_group_unmap; 1257 item_class->draw = gnome_canvas_group_draw; 1258 item_class->point = gnome_canvas_group_point; 1259 item_class->bounds = gnome_canvas_group_bounds; 1260 } 1261 1262 /* Object initialization function for GnomeCanvasGroup */ 1263 static void 1264 gnome_canvas_group_init (GnomeCanvasGroup *group) 1265 { 1266 } 1267 1268 /* Set_property handler for canvas groups */ 1269 static void 1270 gnome_canvas_group_set_property (GObject *gobject, 1271 guint property_id, 1272 const GValue *value, 1273 GParamSpec *pspec) 1274 { 1275 GnomeCanvasItem *item; 1276 1277 g_return_if_fail (GNOME_IS_CANVAS_GROUP (gobject)); 1278 1279 item = GNOME_CANVAS_ITEM (gobject); 1280 1281 switch (property_id) { 1282 case GROUP_PROP_X: 1283 item->matrix.x0 = g_value_get_double (value); 1284 break; 1285 1286 case GROUP_PROP_Y: 1287 item->matrix.y0 = g_value_get_double (value); 1288 break; 1289 1290 default: 1291 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec); 1292 break; 1293 } 1294 } 1295 1296 /* Get_property handler for canvas groups */ 1297 static void 1298 gnome_canvas_group_get_property (GObject *gobject, 1299 guint property_id, 1300 GValue *value, 1301 GParamSpec *pspec) 1302 { 1303 GnomeCanvasItem *item; 1304 1305 g_return_if_fail (GNOME_IS_CANVAS_GROUP (gobject)); 1306 1307 item = GNOME_CANVAS_ITEM (gobject); 1308 1309 switch (property_id) { 1310 case GROUP_PROP_X: 1311 g_value_set_double (value, item->matrix.x0); 1312 break; 1313 1314 case GROUP_PROP_Y: 1315 g_value_set_double (value, item->matrix.y0); 1316 break; 1317 1318 default: 1319 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec); 1320 break; 1321 } 1322 } 1323 1324 /* Dispose handler for canvas groups */ 1325 static void 1326 gnome_canvas_group_dispose (GnomeCanvasItem *object) 1327 { 1328 GnomeCanvasGroup *group; 1329 1330 g_return_if_fail (GNOME_IS_CANVAS_GROUP (object)); 1331 1332 group = GNOME_CANVAS_GROUP (object); 1333 1334 while (group->item_list) { 1335 /* child is unref'ed by the child's group_remove (). */ 1336 g_object_run_dispose (G_OBJECT (group->item_list->data)); 1337 } 1338 1339 GNOME_CANVAS_ITEM_CLASS (gnome_canvas_group_parent_class)-> 1340 dispose (object); 1341 } 1342 1343 /* Update handler for canvas groups */ 1344 static void 1345 gnome_canvas_group_update (GnomeCanvasItem *item, 1346 const cairo_matrix_t *i2c, 1347 gint flags) 1348 { 1349 GnomeCanvasGroup *group; 1350 GList *list; 1351 GnomeCanvasItem *i; 1352 gdouble x1, y1, x2, y2; 1353 1354 group = GNOME_CANVAS_GROUP (item); 1355 1356 GNOME_CANVAS_ITEM_CLASS (gnome_canvas_group_parent_class)-> 1357 update (item, i2c, flags); 1358 1359 x1 = G_MAXDOUBLE; 1360 y1 = G_MAXDOUBLE; 1361 x2 = -G_MAXDOUBLE; 1362 y2 = -G_MAXDOUBLE; 1363 1364 for (list = group->item_list; list; list = list->next) { 1365 i = list->data; 1366 1367 gnome_canvas_item_invoke_update (i, i2c, flags); 1368 1369 x1 = MIN (x1, i->x1); 1370 x2 = MAX (x2, i->x2); 1371 y1 = MIN (y1, i->y1); 1372 y2 = MAX (y2, i->y2); 1373 } 1374 if (x1 >= x2 || y1 >= y2) { 1375 item->x1 = item->x2 = item->y1 = item->y2 = 0; 1376 } else { 1377 item->x1 = x1; 1378 item->y1 = y1; 1379 item->x2 = x2; 1380 item->y2 = y2; 1381 } 1382 } 1383 1384 /* Realize handler for canvas groups */ 1385 static void 1386 gnome_canvas_group_realize (GnomeCanvasItem *item) 1387 { 1388 GnomeCanvasGroup *group; 1389 GList *list; 1390 GnomeCanvasItem *i; 1391 1392 group = GNOME_CANVAS_GROUP (item); 1393 1394 for (list = group->item_list; list; list = list->next) { 1395 i = list->data; 1396 1397 if (!(i->flags & GNOME_CANVAS_ITEM_REALIZED)) 1398 (* GNOME_CANVAS_ITEM_GET_CLASS (i)->realize) (i); 1399 } 1400 1401 GNOME_CANVAS_ITEM_CLASS (gnome_canvas_group_parent_class)-> 1402 realize (item); 1403 } 1404 1405 /* Unrealize handler for canvas groups */ 1406 static void 1407 gnome_canvas_group_unrealize (GnomeCanvasItem *item) 1408 { 1409 GnomeCanvasGroup *group; 1410 GList *list; 1411 GnomeCanvasItem *i; 1412 1413 group = GNOME_CANVAS_GROUP (item); 1414 1415 for (list = group->item_list; list; list = list->next) { 1416 i = list->data; 1417 1418 if (i->flags & GNOME_CANVAS_ITEM_REALIZED) 1419 (* GNOME_CANVAS_ITEM_GET_CLASS (i)->unrealize) (i); 1420 } 1421 1422 GNOME_CANVAS_ITEM_CLASS (gnome_canvas_group_parent_class)-> 1423 unrealize (item); 1424 } 1425 1426 /* Map handler for canvas groups */ 1427 static void 1428 gnome_canvas_group_map (GnomeCanvasItem *item) 1429 { 1430 GnomeCanvasGroup *group; 1431 GList *list; 1432 GnomeCanvasItem *i; 1433 1434 group = GNOME_CANVAS_GROUP (item); 1435 1436 for (list = group->item_list; list; list = list->next) { 1437 i = list->data; 1438 1439 if (!(i->flags & GNOME_CANVAS_ITEM_MAPPED)) 1440 (* GNOME_CANVAS_ITEM_GET_CLASS (i)->map) (i); 1441 } 1442 1443 GNOME_CANVAS_ITEM_CLASS (gnome_canvas_group_parent_class)->map (item); 1444 } 1445 1446 /* Unmap handler for canvas groups */ 1447 static void 1448 gnome_canvas_group_unmap (GnomeCanvasItem *item) 1449 { 1450 GnomeCanvasGroup *group; 1451 GList *list; 1452 GnomeCanvasItem *i; 1453 1454 group = GNOME_CANVAS_GROUP (item); 1455 1456 for (list = group->item_list; list; list = list->next) { 1457 i = list->data; 1458 1459 if (i->flags & GNOME_CANVAS_ITEM_MAPPED) 1460 (* GNOME_CANVAS_ITEM_GET_CLASS (i)->unmap) (i); 1461 } 1462 1463 GNOME_CANVAS_ITEM_CLASS (gnome_canvas_group_parent_class)->unmap (item); 1464 } 1465 1466 /* Draw handler for canvas groups */ 1467 static void 1468 gnome_canvas_group_draw (GnomeCanvasItem *item, 1469 cairo_t *cr, 1470 gint x, 1471 gint y, 1472 gint width, 1473 gint height) 1474 { 1475 GnomeCanvasGroup *group; 1476 GList *list; 1477 GnomeCanvasItem *child = NULL; 1478 1479 group = GNOME_CANVAS_GROUP (item); 1480 1481 for (list = group->item_list; list; list = list->next) { 1482 child = list->data; 1483 1484 if ((child->flags & GNOME_CANVAS_ITEM_VISIBLE) 1485 && ((child->x1 < (x + width)) 1486 && (child->y1 < (y + height)) 1487 && (child->x2 > x) 1488 && (child->y2 > y))) { 1489 cairo_save (cr); 1490 1491 GNOME_CANVAS_ITEM_GET_CLASS (child)->draw ( 1492 child, cr, x, y, width, height); 1493 1494 cairo_restore (cr); 1495 } 1496 } 1497 } 1498 1499 /* Point handler for canvas groups */ 1500 static GnomeCanvasItem * 1501 gnome_canvas_group_point (GnomeCanvasItem *item, 1502 gdouble x, 1503 gdouble y, 1504 gint cx, 1505 gint cy) 1506 { 1507 GnomeCanvasGroup *group; 1508 GList *list; 1509 GnomeCanvasItem *child, *point_item; 1510 1511 group = GNOME_CANVAS_GROUP (item); 1512 1513 for (list = g_list_last (group->item_list); list; list = list->prev) { 1514 child = list->data; 1515 1516 if ((child->x1 > cx) || (child->y1 > cy)) 1517 continue; 1518 1519 if ((child->x2 < cx) || (child->y2 < cy)) 1520 continue; 1521 1522 if (!(child->flags & GNOME_CANVAS_ITEM_VISIBLE)) 1523 continue; 1524 1525 point_item = gnome_canvas_item_invoke_point (child, x, y, cx, cy); 1526 if (point_item) 1527 return point_item; 1528 } 1529 1530 return NULL; 1531 } 1532 1533 /* Bounds handler for canvas groups */ 1534 static void 1535 gnome_canvas_group_bounds (GnomeCanvasItem *item, 1536 gdouble *x1, 1537 gdouble *y1, 1538 gdouble *x2, 1539 gdouble *y2) 1540 { 1541 GnomeCanvasGroup *group; 1542 GnomeCanvasItem *child; 1543 GList *list; 1544 gdouble tx1, ty1, tx2, ty2; 1545 gdouble minx, miny, maxx, maxy; 1546 gint set; 1547 1548 group = GNOME_CANVAS_GROUP (item); 1549 1550 /* Get the bounds of the first visible item */ 1551 1552 child = NULL; /* Unnecessary but eliminates a warning. */ 1553 1554 set = FALSE; 1555 1556 for (list = group->item_list; list; list = list->next) { 1557 child = list->data; 1558 1559 if (child->flags & GNOME_CANVAS_ITEM_VISIBLE) { 1560 set = TRUE; 1561 gnome_canvas_item_get_bounds (child, &minx, &miny, &maxx, &maxy); 1562 break; 1563 } 1564 } 1565 1566 /* If there were no visible items, return an empty bounding box */ 1567 1568 if (!set) { 1569 *x1 = *y1 = *x2 = *y2 = 0.0; 1570 return; 1571 } 1572 1573 /* Now we can grow the bounds using the rest of the items */ 1574 1575 list = list->next; 1576 1577 for (; list; list = list->next) { 1578 child = list->data; 1579 1580 if (!(child->flags & GNOME_CANVAS_ITEM_VISIBLE)) 1581 continue; 1582 1583 gnome_canvas_item_get_bounds (child, &tx1, &ty1, &tx2, &ty2); 1584 1585 if (tx1 < minx)
The left operand of '<' is a garbage value
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

The right operand of '<' is a garbage value
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

The right operand of '<' is a garbage value
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

The left operand of '<' is a garbage value
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

1586 minx = tx1; 1587 1588 if (ty1 < miny) 1589 miny = ty1; 1590 1591 if (tx2 > maxx) 1592 maxx = tx2; 1593 1594 if (ty2 > maxy) 1595 maxy = ty2; 1596 } 1597 1598 *x1 = minx;
Assigned value is garbage or undefined
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

Assigned value is garbage or undefined
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

1599 *y1 = miny; 1600 *x2 = maxx; 1601 *y2 = maxy; 1602 } 1603 1604 /* Adds an item to a group */ 1605 static void 1606 group_add (GnomeCanvasGroup *group, 1607 GnomeCanvasItem *item) 1608 { 1609 g_object_ref_sink (item); 1610 1611 if (!group->item_list) { 1612 group->item_list = g_list_append (group->item_list, item); 1613 group->item_list_end = group->item_list; 1614 } else 1615 group->item_list_end = g_list_append (group->item_list_end, item)->next; 1616 1617 if (group->item.flags & GNOME_CANVAS_ITEM_REALIZED) 1618 (* GNOME_CANVAS_ITEM_GET_CLASS (item)->realize) (item); 1619 1620 if (group->item.flags & GNOME_CANVAS_ITEM_MAPPED) 1621 (* GNOME_CANVAS_ITEM_GET_CLASS (item)->map) (item); 1622 1623 g_object_notify (G_OBJECT (item), "parent"); 1624 } 1625 1626 /* Removes an item from a group */ 1627 static void 1628 group_remove (GnomeCanvasGroup *group, 1629 GnomeCanvasItem *item) 1630 { 1631 GList *children; 1632 1633 g_return_if_fail (GNOME_IS_CANVAS_GROUP (group)); 1634 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item)); 1635 1636 for (children = group->item_list; children; children = children->next) 1637 if (children->data == item) { 1638 if (item->flags & GNOME_CANVAS_ITEM_MAPPED) 1639 (* GNOME_CANVAS_ITEM_GET_CLASS (item)->unmap) (item); 1640 1641 if (item->flags & GNOME_CANVAS_ITEM_REALIZED) 1642 (* GNOME_CANVAS_ITEM_GET_CLASS (item)->unrealize) (item); 1643 1644 /* Unparent the child */ 1645 1646 item->parent = NULL; 1647 g_object_unref (item); 1648 1649 /* Remove it from the list */ 1650 1651 if (children == group->item_list_end) 1652 group->item_list_end = children->prev; 1653 1654 group->item_list = g_list_remove_link (group->item_list, children); 1655 g_list_free (children); 1656 break; 1657 } 1658 } 1659 1660 /*** GnomeCanvas ***/ 1661 1662 enum { 1663 DRAW_BACKGROUND, 1664 LAST_SIGNAL 1665 }; 1666 1667 static void gnome_canvas_dispose (GObject *object); 1668 static void gnome_canvas_map (GtkWidget *widget); 1669 static void gnome_canvas_unmap (GtkWidget *widget); 1670 static void gnome_canvas_realize (GtkWidget *widget); 1671 static void gnome_canvas_unrealize (GtkWidget *widget); 1672 static void gnome_canvas_size_allocate (GtkWidget *widget, 1673 GtkAllocation *allocation); 1674 static gint gnome_canvas_draw (GtkWidget *widget, 1675 cairo_t *cr); 1676 static gint gnome_canvas_button (GtkWidget *widget, 1677 GdkEventButton *event); 1678 static gint gnome_canvas_motion (GtkWidget *widget, 1679 GdkEventMotion *event); 1680 static gboolean gnome_canvas_key (GtkWidget *widget, 1681 GdkEventKey *event); 1682 static gint gnome_canvas_crossing (GtkWidget *widget, 1683 GdkEventCrossing *event); 1684 static gint gnome_canvas_focus_in (GtkWidget *widget, 1685 GdkEventFocus *event); 1686 static gint gnome_canvas_focus_out (GtkWidget *widget, 1687 GdkEventFocus *event); 1688 static void gnome_canvas_request_update_real (GnomeCanvas *canvas); 1689 static void gnome_canvas_draw_background (GnomeCanvas *canvas, 1690 cairo_t *cr, 1691 gint x, 1692 gint y, 1693 gint width, 1694 gint height); 1695 1696 static guint canvas_signals[LAST_SIGNAL]; 1697 1698 enum { 1699 PROP_0, 1700 PROP_FOCUSED_ITEM, 1701 }; 1702 1703 G_DEFINE_TYPE ( 1704 GnomeCanvas, 1705 gnome_canvas, 1706 GTK_TYPE_LAYOUT) 1707 1708 static void 1709 gnome_canvas_paint_rect (GnomeCanvas *canvas, 1710 cairo_t *cr, 1711 gint x0, 1712 gint y0, 1713 gint x1, 1714 gint y1) 1715 { 1716 GtkWidget *widget; 1717 GtkAllocation allocation; 1718 GtkScrollable *scrollable; 1719 GtkAdjustment *hadjustment; 1720 GtkAdjustment *vadjustment; 1721 gint draw_x1, draw_y1; 1722 gint draw_x2, draw_y2; 1723 gint draw_width, draw_height; 1724 gdouble hadjustment_value; 1725 gdouble vadjustment_value; 1726 1727 g_return_if_fail (!canvas->need_update); 1728 1729 widget = GTK_WIDGET (canvas); 1730 gtk_widget_get_allocation (widget, &allocation); 1731 1732 scrollable = GTK_SCROLLABLE (canvas); 1733 hadjustment = gtk_scrollable_get_hadjustment (scrollable); 1734 vadjustment = gtk_scrollable_get_vadjustment (scrollable); 1735 1736 hadjustment_value = gtk_adjustment_get_value (hadjustment); 1737 vadjustment_value = gtk_adjustment_get_value (vadjustment); 1738 1739 draw_x1 = MAX (x0, hadjustment_value - canvas->zoom_xofs); 1740 draw_y1 = MAX (y0, vadjustment_value - canvas->zoom_yofs); 1741 draw_x2 = MIN (draw_x1 + allocation.width, x1); 1742 draw_y2 = MIN (draw_y1 + allocation.height, y1); 1743 1744 draw_width = draw_x2 - draw_x1; 1745 draw_height = draw_y2 - draw_y1; 1746 1747 if (draw_width < 1 || draw_height < 1) 1748 return; 1749 1750 canvas->draw_xofs = draw_x1; 1751 canvas->draw_yofs = draw_y1; 1752 1753 cairo_save (cr); 1754 1755 g_signal_emit ( 1756 canvas, canvas_signals[DRAW_BACKGROUND], 0, cr, 1757 draw_x1, draw_y1, draw_width, draw_height); 1758 1759 cairo_restore (cr); 1760 1761 if (canvas->root->flags & GNOME_CANVAS_ITEM_VISIBLE) { 1762 cairo_save (cr); 1763 1764 (* GNOME_CANVAS_ITEM_GET_CLASS (canvas->root)->draw) ( 1765 canvas->root, cr, 1766 draw_x1, draw_y1, 1767 draw_width, draw_height); 1768 1769 cairo_restore (cr); 1770 } 1771 } 1772 1773 static void 1774 gnome_canvas_get_property (GObject *object, 1775 guint property_id, 1776 GValue *value, 1777 GParamSpec *pspec) 1778 { 1779 switch (property_id) { 1780 case PROP_FOCUSED_ITEM: 1781 g_value_set_object (value, GNOME_CANVAS (object)->focused_item); 1782 break; 1783 default: 1784 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); 1785 break; 1786 } 1787 } 1788 1789 static void 1790 gnome_canvas_set_property (GObject *object, 1791 guint property_id, 1792 const GValue *value, 1793 GParamSpec *pspec) 1794 { 1795 switch (property_id) { 1796 case PROP_FOCUSED_ITEM: 1797 GNOME_CANVAS (object)->focused_item = g_value_get_object (value); 1798 break; 1799 default: 1800 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); 1801 break; 1802 } 1803 } 1804 1805 /* Class initialization function for GnomeCanvasClass */ 1806 static void 1807 gnome_canvas_class_init (GnomeCanvasClass *class) 1808 { 1809 GObjectClass *object_class; 1810 GtkWidgetClass *widget_class; 1811 1812 object_class = (GObjectClass *) class; 1813 widget_class = (GtkWidgetClass *) class; 1814 1815 object_class->set_property = gnome_canvas_set_property; 1816 object_class->get_property = gnome_canvas_get_property; 1817 object_class->dispose = gnome_canvas_dispose; 1818 1819 widget_class->map = gnome_canvas_map; 1820 widget_class->unmap = gnome_canvas_unmap; 1821 widget_class->realize = gnome_canvas_realize; 1822 widget_class->unrealize = gnome_canvas_unrealize; 1823 widget_class->size_allocate = gnome_canvas_size_allocate; 1824 widget_class->draw = gnome_canvas_draw; 1825 widget_class->button_press_event = gnome_canvas_button; 1826 widget_class->button_release_event = gnome_canvas_button; 1827 widget_class->motion_notify_event = gnome_canvas_motion; 1828 widget_class->key_press_event = gnome_canvas_key; 1829 widget_class->key_release_event = gnome_canvas_key; 1830 widget_class->enter_notify_event = gnome_canvas_crossing; 1831 widget_class->leave_notify_event = gnome_canvas_crossing; 1832 widget_class->focus_in_event = gnome_canvas_focus_in; 1833 widget_class->focus_out_event = gnome_canvas_focus_out; 1834 1835 class->draw_background = gnome_canvas_draw_background; 1836 class->request_update = gnome_canvas_request_update_real; 1837 1838 g_object_class_install_property ( 1839 object_class, 1840 PROP_FOCUSED_ITEM, 1841 g_param_spec_object ( 1842 "focused_item", 1843 NULL, 1844 NULL, 1845 GNOME_TYPE_CANVAS_ITEM, 1846 G_PARAM_READABLE | 1847 G_PARAM_WRITABLE)); 1848 1849 canvas_signals[DRAW_BACKGROUND] = g_signal_new ( 1850 "draw_background", 1851 G_TYPE_FROM_CLASS (object_class), 1852 G_SIGNAL_RUN_LAST, 1853 G_STRUCT_OFFSET (GnomeCanvasClass, draw_background), 1854 NULL, NULL, NULL, 1855 G_TYPE_NONE, 5, 1856 CAIRO_GOBJECT_TYPE_CONTEXT, 1857 G_TYPE_INT, 1858 G_TYPE_INT, 1859 G_TYPE_INT, 1860 G_TYPE_INT); 1861 1862 gail_canvas_init (); 1863 } 1864 1865 /* Callback used when the root item of a canvas is destroyed. The user should 1866 * never ever do this, so we panic if this happens. 1867 */ 1868 G_GNUC_NORETURN static void 1869 panic_root_finalized (gpointer data, 1870 GObject *gone_object) 1871 { 1872 g_error ("Eeeek, root item %p of canvas %p was destroyed!", gone_object, data); 1873 } 1874 1875 /* Object initialization function for GnomeCanvas */ 1876 static void 1877 gnome_canvas_init (GnomeCanvas *canvas) 1878 { 1879 GtkLayout *layout; 1880 guint layout_width, layout_height; 1881 1882 layout = GTK_LAYOUT (canvas); 1883 gtk_layout_get_size (layout, &layout_width, &layout_height); 1884 1885 gtk_widget_set_can_focus (GTK_WIDGET (canvas), TRUE); 1886 1887 canvas->need_update = FALSE; 1888 canvas->idle_id = 0; 1889 1890 canvas->scroll_x1 = 0.0; 1891 canvas->scroll_y1 = 0.0; 1892 canvas->scroll_x2 = layout_width; 1893 canvas->scroll_y2 = layout_height; 1894 1895 canvas->pick_event.type = GDK_LEAVE_NOTIFY; 1896 canvas->pick_event.crossing.x = 0; 1897 canvas->pick_event.crossing.y = 0; 1898 1899 gtk_scrollable_set_hadjustment (GTK_SCROLLABLE (canvas), NULL); 1900 gtk_scrollable_set_vadjustment (GTK_SCROLLABLE (canvas), NULL); 1901 1902 /* Create the root item as a special case */ 1903 1904 canvas->root = GNOME_CANVAS_ITEM ( 1905 g_object_new (gnome_canvas_group_get_type (), NULL)); 1906 canvas->root->canvas = canvas; 1907 1908 g_object_ref_sink (canvas->root); 1909 1910 g_object_weak_ref (G_OBJECT (canvas->root), panic_root_finalized, canvas); 1911 1912 canvas->need_repick = TRUE; 1913 } 1914 1915 /* Convenience function to remove the idle handler of a canvas */ 1916 static void 1917 remove_idle (GnomeCanvas *canvas) 1918 { 1919 if (canvas->idle_id == 0) 1920 return; 1921 1922 g_source_remove (canvas->idle_id); 1923 canvas->idle_id = 0; 1924 } 1925 1926 /* Removes the transient state of the canvas (idle handler, grabs). */ 1927 static void 1928 shutdown_transients (GnomeCanvas *canvas) 1929 { 1930 if (canvas->grabbed_item) { 1931 canvas->grabbed_item = NULL; 1932 gdk_pointer_ungrab (GDK_CURRENT_TIME); 1933 } 1934 1935 remove_idle (canvas); 1936 } 1937 1938 /* Dispose handler for GnomeCanvas */ 1939 static void 1940 gnome_canvas_dispose (GObject *object) 1941 { 1942 GnomeCanvas *canvas; 1943 1944 g_return_if_fail (GNOME_IS_CANVAS (object)); 1945 1946 /* remember, dispose can be run multiple times! */ 1947 1948 canvas = GNOME_CANVAS (object); 1949 1950 if (canvas->root) { 1951 g_object_weak_unref (G_OBJECT (canvas->root), panic_root_finalized, canvas); 1952 g_object_unref (canvas->root); 1953 canvas->root = NULL; 1954 } 1955 1956 shutdown_transients (canvas); 1957 1958 /* Chain up to parent's dispose() method. */ 1959 G_OBJECT_CLASS (gnome_canvas_parent_class)->dispose (object); 1960 } 1961 1962 /** 1963 * gnome_canvas_new: 1964 * 1965 * Creates a new empty canvas in non-antialiased mode. 1966 * 1967 * Return value: A newly-created canvas. 1968 **/ 1969 GtkWidget * 1970 gnome_canvas_new (void) 1971 { 1972 return GTK_WIDGET (g_object_new (gnome_canvas_get_type (), NULL)); 1973 } 1974 1975 /* Map handler for the canvas */ 1976 static void 1977 gnome_canvas_map (GtkWidget *widget) 1978 { 1979 GnomeCanvas *canvas; 1980 1981 g_return_if_fail (GNOME_IS_CANVAS (widget)); 1982 1983 /* Normal widget mapping stuff */ 1984 1985 GTK_WIDGET_CLASS (gnome_canvas_parent_class)->map (widget); 1986 1987 canvas = GNOME_CANVAS (widget); 1988 1989 if (canvas->need_update) 1990 add_idle (canvas); 1991 1992 /* Map items */ 1993 1994 if (GNOME_CANVAS_ITEM_GET_CLASS (canvas->root)->map) 1995 (* GNOME_CANVAS_ITEM_GET_CLASS (canvas->root)->map) (canvas->root); 1996 } 1997 1998 /* Unmap handler for the canvas */ 1999 static void 2000 gnome_canvas_unmap (GtkWidget *widget) 2001 { 2002 GnomeCanvas *canvas; 2003 2004 g_return_if_fail (GNOME_IS_CANVAS (widget)); 2005 2006 canvas = GNOME_CANVAS (widget); 2007 2008 shutdown_transients (canvas); 2009 2010 /* Unmap items */ 2011 2012 if (GNOME_CANVAS_ITEM_GET_CLASS (canvas->root)->unmap) 2013 (* GNOME_CANVAS_ITEM_GET_CLASS (canvas->root)->unmap) (canvas->root); 2014 2015 /* Normal widget unmapping stuff */ 2016 2017 GTK_WIDGET_CLASS (gnome_canvas_parent_class)->unmap (widget); 2018 } 2019 2020 /* Realize handler for the canvas */ 2021 static void 2022 gnome_canvas_realize (GtkWidget *widget) 2023 { 2024 GnomeCanvas *canvas; 2025 GtkLayout *layout; 2026 GdkWindow *bin_window; 2027 2028 g_return_if_fail (GNOME_IS_CANVAS (widget)); 2029 2030 /* Normal widget realization stuff */ 2031 2032 GTK_WIDGET_CLASS (gnome_canvas_parent_class)->realize (widget); 2033 2034 canvas = GNOME_CANVAS (widget); 2035 2036 layout = GTK_LAYOUT (canvas); 2037 bin_window = gtk_layout_get_bin_window (layout); 2038 2039 gdk_window_set_events ( 2040 bin_window, 2041 (gdk_window_get_events (bin_window) 2042 | GDK_EXPOSURE_MASK 2043 | GDK_SCROLL_MASK 2044 | GDK_BUTTON_PRESS_MASK 2045 | GDK_BUTTON_RELEASE_MASK 2046 | GDK_POINTER_MOTION_MASK 2047 | GDK_KEY_PRESS_MASK 2048 | GDK_KEY_RELEASE_MASK 2049 | GDK_ENTER_NOTIFY_MASK 2050 | GDK_LEAVE_NOTIFY_MASK 2051 | GDK_FOCUS_CHANGE_MASK)); 2052 2053 /* Create our own temporary pixmap gc and realize all the items */ 2054 2055 (* GNOME_CANVAS_ITEM_GET_CLASS (canvas->root)->realize) (canvas->root); 2056 } 2057 2058 /* Unrealize handler for the canvas */ 2059 static void 2060 gnome_canvas_unrealize (GtkWidget *widget) 2061 { 2062 GnomeCanvas *canvas; 2063 2064 g_return_if_fail (GNOME_IS_CANVAS (widget)); 2065 2066 canvas = GNOME_CANVAS (widget); 2067 2068 shutdown_transients (canvas); 2069 2070 /* Unrealize items and parent widget */ 2071 2072 (* GNOME_CANVAS_ITEM_GET_CLASS (canvas->root)->unrealize) (canvas->root); 2073 2074 GTK_WIDGET_CLASS (gnome_canvas_parent_class)->unrealize (widget); 2075 } 2076 2077 /* Handles scrolling of the canvas. Adjusts the scrolling and zooming offset to 2078 * keep as much as possible of the canvas scrolling region in view. 2079 */ 2080 static void 2081 scroll_to (GnomeCanvas *canvas, 2082 gint cx, 2083 gint cy) 2084 { 2085 GtkWidget *widget; 2086 GtkAllocation allocation; 2087 GtkScrollable *scrollable; 2088 GtkAdjustment *hadjustment; 2089 GtkAdjustment *vadjustment; 2090 guint layout_width, layout_height; 2091 gint scroll_width, scroll_height; 2092 gint right_limit, bottom_limit; 2093 gint old_zoom_xofs, old_zoom_yofs; 2094 gint canvas_width, canvas_height; 2095 2096 widget = GTK_WIDGET (canvas); 2097 gtk_widget_get_allocation (widget, &allocation); 2098 2099 scrollable = GTK_SCROLLABLE (canvas); 2100 hadjustment = gtk_scrollable_get_hadjustment (scrollable); 2101 vadjustment = gtk_scrollable_get_vadjustment (scrollable); 2102 2103 gtk_layout_get_size (GTK_LAYOUT (canvas), &layout_width, &layout_height); 2104 2105 canvas_width = allocation.width; 2106 canvas_height = allocation.height; 2107 2108 scroll_width = 2109 floor ((canvas->scroll_x2 - canvas->scroll_x1) + 0.5); 2110 scroll_height = 2111 floor ((canvas->scroll_y2 - canvas->scroll_y1) + 0.5); 2112 2113 right_limit = scroll_width - canvas_width; 2114 bottom_limit = scroll_height - canvas_height; 2115 2116 old_zoom_xofs = canvas->zoom_xofs; 2117 old_zoom_yofs = canvas->zoom_yofs; 2118 2119 if (right_limit < 0) { 2120 cx = 0; 2121 canvas->zoom_xofs = (canvas_width - scroll_width) / 2; 2122 scroll_width = canvas_width; 2123 } else if (cx < 0) { 2124 cx = 0; 2125 canvas->zoom_xofs = 0; 2126 } else if (cx > right_limit) { 2127 cx = right_limit; 2128 canvas->zoom_xofs = 0; 2129 } else 2130 canvas->zoom_xofs = 0; 2131 2132 if (bottom_limit < 0) { 2133 cy = 0; 2134 canvas->zoom_yofs = (canvas_height - scroll_height) / 2; 2135 scroll_height = canvas_height; 2136 } else if (cy < 0) { 2137 cy = 0; 2138 canvas->zoom_yofs = 0; 2139 } else if (cy > bottom_limit) { 2140 cy = bottom_limit; 2141 canvas->zoom_yofs = 0; 2142 } else 2143 canvas->zoom_yofs = 0; 2144 2145 if ((canvas->zoom_xofs != old_zoom_xofs) || 2146 (canvas->zoom_yofs != old_zoom_yofs)) { 2147 /* This can only occur, if either canvas size or widget 2148 * size changes. So I think we can request full redraw 2149 * here. The reason is, that coverage UTA will be 2150 * invalidated by offset change. */ 2151 /* FIXME Strictly this is not correct - we have to remove 2152 * our own idle (Lauris) */ 2153 /* More stuff - we have to mark root as needing fresh affine 2154 * (Lauris) */ 2155 if (!(canvas->root->flags & GNOME_CANVAS_ITEM_NEED_AFFINE)) { 2156 canvas->root->flags |= GNOME_CANVAS_ITEM_NEED_AFFINE; 2157 gnome_canvas_request_update (canvas); 2158 } 2159 gtk_widget_queue_draw (GTK_WIDGET (canvas)); 2160 } 2161 2162 if (hadjustment) 2163 gtk_adjustment_set_value (hadjustment, cx); 2164 2165 if (vadjustment) 2166 gtk_adjustment_set_value (vadjustment, cy); 2167 2168 if ((scroll_width != (gint) layout_width) 2169 || (scroll_height != (gint) layout_height)) 2170 gtk_layout_set_size (GTK_LAYOUT (canvas), scroll_width, scroll_height); 2171 } 2172 2173 /* Size allocation handler for the canvas */ 2174 static void 2175 gnome_canvas_size_allocate (GtkWidget *widget, 2176 GtkAllocation *allocation) 2177 { 2178 GtkScrollable *scrollable; 2179 GtkAdjustment *hadjustment; 2180 GtkAdjustment *vadjustment; 2181 2182 g_return_if_fail (GNOME_IS_CANVAS (widget)); 2183 g_return_if_fail (allocation != NULL); 2184 2185 GTK_WIDGET_CLASS (gnome_canvas_parent_class)-> 2186 size_allocate (widget, allocation); 2187 2188 scrollable = GTK_SCROLLABLE (widget); 2189 hadjustment = gtk_scrollable_get_hadjustment (scrollable); 2190 vadjustment = gtk_scrollable_get_vadjustment (scrollable); 2191 2192 /* Recenter the view, if appropriate */ 2193 2194 g_object_freeze_notify (G_OBJECT (hadjustment)); 2195 g_object_freeze_notify (G_OBJECT (vadjustment)); 2196 2197 gtk_adjustment_set_page_size (hadjustment, allocation->width); 2198 gtk_adjustment_set_page_increment (hadjustment, allocation->width / 2); 2199 2200 gtk_adjustment_set_page_size (vadjustment, allocation->height); 2201 gtk_adjustment_set_page_increment (vadjustment, allocation->height / 2); 2202 2203 scroll_to ( 2204 GNOME_CANVAS (widget), 2205 gtk_adjustment_get_value (hadjustment), 2206 gtk_adjustment_get_value (vadjustment)); 2207 2208 g_object_thaw_notify (G_OBJECT (hadjustment)); 2209 g_object_thaw_notify (G_OBJECT (vadjustment)); 2210 } 2211 2212 static gboolean 2213 gnome_canvas_draw (GtkWidget *widget, 2214 cairo_t *cr) 2215 { 2216 GnomeCanvas *canvas = GNOME_CANVAS (widget); 2217 cairo_rectangle_int_t rect; 2218 GtkLayout *layout; 2219 GtkAdjustment *hadjustment; 2220 GtkAdjustment *vadjustment; 2221 gdouble hadjustment_value; 2222 gdouble vadjustment_value; 2223 2224 layout = GTK_LAYOUT (canvas); 2225 hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (layout)); 2226 vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (layout)); 2227 2228 hadjustment_value = gtk_adjustment_get_value (hadjustment); 2229 vadjustment_value = gtk_adjustment_get_value (vadjustment); 2230 2231 gdk_cairo_get_clip_rectangle (cr, &rect); 2232 2233 if (canvas->need_update) { 2234 cairo_matrix_t w2c; 2235 2236 /* We start updating root with w2c matrix */ 2237 gnome_canvas_w2c_matrix (canvas, &w2c); 2238 2239 gnome_canvas_item_invoke_update (canvas->root, &w2c, 0); 2240 2241 canvas->need_update = FALSE; 2242 } 2243 2244 cairo_save (cr); 2245 cairo_translate ( 2246 cr, 2247 -canvas->zoom_xofs + rect.x, 2248 -canvas->zoom_yofs + rect.y); 2249 2250 rect.x += hadjustment_value; 2251 rect.y += vadjustment_value; 2252 2253 /* No pending updates, draw exposed area immediately */ 2254 gnome_canvas_paint_rect ( 2255 canvas, cr, 2256 rect.x, rect.y, 2257 rect.x + rect.width, 2258 rect.y + rect.height); 2259 cairo_restore (cr); 2260 2261 /* And call expose on parent container class */ 2262 GTK_WIDGET_CLASS (gnome_canvas_parent_class)->draw (widget, cr); 2263 2264 return FALSE; 2265 } 2266 2267 /* Emits an event for an item in the canvas, be it the current item, grabbed 2268 * item, or focused item, as appropriate. 2269 */ 2270 2271 static gint 2272 emit_event (GnomeCanvas *canvas, 2273 GdkEvent *event) 2274 { 2275 GdkEvent *ev; 2276 gint finished; 2277 GnomeCanvasItem *item; 2278 GnomeCanvasItem *parent; 2279 guint mask; 2280 2281 /* Perform checks for grabbed items */ 2282 2283 if (canvas->grabbed_item && 2284 !is_descendant (canvas->current_item, canvas->grabbed_item)) { 2285 /* I think this warning is annoying and I don't know what it's for 2286 * so I'll disable it for now. 2287 */ 2288 /* g_warning ("emit_event() returning FALSE!\n");*/ 2289 return FALSE; 2290 } 2291 2292 if (canvas->grabbed_item) { 2293 switch (event->type) { 2294 case GDK_ENTER_NOTIFY: 2295 mask = GDK_ENTER_NOTIFY_MASK; 2296 break; 2297 2298 case GDK_LEAVE_NOTIFY: 2299 mask = GDK_LEAVE_NOTIFY_MASK; 2300 break; 2301 2302 case GDK_MOTION_NOTIFY: 2303 mask = GDK_POINTER_MOTION_MASK; 2304 break; 2305 2306 case GDK_BUTTON_PRESS: 2307 case GDK_2BUTTON_PRESS: 2308 case GDK_3BUTTON_PRESS: 2309 mask = GDK_BUTTON_PRESS_MASK; 2310 break; 2311 2312 case GDK_BUTTON_RELEASE: 2313 mask = GDK_BUTTON_RELEASE_MASK; 2314 break; 2315 2316 case GDK_KEY_PRESS: 2317 mask = GDK_KEY_PRESS_MASK; 2318 break; 2319 2320 case GDK_KEY_RELEASE: 2321 mask = GDK_KEY_RELEASE_MASK; 2322 break; 2323 2324 case GDK_SCROLL: 2325 mask = GDK_SCROLL_MASK; 2326 break; 2327 2328 default: 2329 mask = 0; 2330 break; 2331 } 2332 2333 if (!(mask & canvas->grabbed_event_mask)) 2334 return FALSE; 2335 } 2336 2337 /* Convert to world coordinates -- we have two cases because of diferent 2338 * offsets of the fields in the event structures. 2339 */ 2340 2341 ev = gdk_event_copy (event); 2342 2343 switch (ev->type) 2344 { 2345 case GDK_ENTER_NOTIFY: 2346 case GDK_LEAVE_NOTIFY: 2347 gnome_canvas_window_to_world ( 2348 canvas, 2349 ev->crossing.x, ev->crossing.y, 2350 &ev->crossing.x, &ev->crossing.y); 2351 break; 2352 2353 case GDK_MOTION_NOTIFY: 2354 case GDK_BUTTON_PRESS: 2355 case GDK_2BUTTON_PRESS: 2356 case GDK_3BUTTON_PRESS: 2357 case GDK_BUTTON_RELEASE: 2358 gnome_canvas_window_to_world ( 2359 canvas, 2360 ev->motion.x, ev->motion.y, 2361 &ev->motion.x, &ev->motion.y); 2362 break; 2363 2364 default: 2365 break; 2366 } 2367 2368 /* Choose where we send the event */ 2369 2370 item = canvas->current_item; 2371 2372 if (canvas->focused_item 2373 && ((event->type == GDK_KEY_PRESS) || 2374 (event->type == GDK_KEY_RELEASE) || 2375 (event->type == GDK_FOCUS_CHANGE))) 2376 item = canvas->focused_item; 2377 2378 /* The event is propagated up the hierarchy (for if someone connected to 2379 * a group instead of a leaf event), and emission is stopped if a 2380 * handler returns TRUE, just like for GtkWidget events. 2381 */ 2382 2383 finished = FALSE; 2384 2385 while (item && !finished) { 2386 g_object_ref (item); 2387 2388 g_signal_emit ( 2389 item, item_signals[ITEM_EVENT], 0, 2390 ev, &finished); 2391 2392 parent = item->parent; 2393 g_object_unref (item); 2394 2395 item = parent; 2396 } 2397 2398 gdk_event_free (ev); 2399 2400 return finished; 2401 } 2402 2403 /* Re-picks the current item in the canvas, based on the event's coordinates. 2404 * Also emits enter/leave events for items as appropriate. 2405 */ 2406 static gint 2407 pick_current_item (GnomeCanvas *canvas, 2408 GdkEvent *event) 2409 { 2410 gint button_down; 2411 gdouble x, y; 2412 gint cx, cy; 2413 gint retval; 2414 2415 retval = FALSE; 2416 2417 /* If a button is down, we'll perform enter and leave events on the 2418 * current item, but not enter on any other item. This is more or less 2419 * like X pointer grabbing for canvas items. 2420 */ 2421 button_down = canvas->state & (GDK_BUTTON1_MASK 2422 | GDK_BUTTON2_MASK 2423 | GDK_BUTTON3_MASK 2424 | GDK_BUTTON4_MASK 2425 | GDK_BUTTON5_MASK); 2426 if (!button_down) 2427 canvas->left_grabbed_item = FALSE; 2428 2429 /* Save the event in the canvas. This is used to synthesize enter and 2430 * leave events in case the current item changes. It is also used to 2431 * re-pick the current item if the current one gets deleted. Also, 2432 * synthesize an enter event. 2433 */ 2434 if (event != &canvas->pick_event) { 2435 if ((event->type == GDK_MOTION_NOTIFY) || 2436 (event->type == GDK_BUTTON_RELEASE)) { 2437 /* these fields have the same offsets in both types of events */ 2438 2439 canvas->pick_event.crossing.type = GDK_ENTER_NOTIFY; 2440 canvas->pick_event.crossing.window = event->motion.window; 2441 canvas->pick_event.crossing.send_event = event->motion.send_event; 2442 canvas->pick_event.crossing.subwindow = NULL; 2443 canvas->pick_event.crossing.x = event->motion.x; 2444 canvas->pick_event.crossing.y = event->motion.y; 2445 canvas->pick_event.crossing.mode = GDK_CROSSING_NORMAL; 2446 canvas->pick_event.crossing.detail = GDK_NOTIFY_NONLINEAR; 2447 canvas->pick_event.crossing.focus = FALSE; 2448 canvas->pick_event.crossing.state = event->motion.state; 2449 2450 /* these fields don't have the same offsets in both types of events */ 2451 2452 if (event->type == GDK_MOTION_NOTIFY) { 2453 canvas->pick_event.crossing.x_root = event->motion.x_root; 2454 canvas->pick_event.crossing.y_root = event->motion.y_root; 2455 } else { 2456 canvas->pick_event.crossing.x_root = event->button.x_root; 2457 canvas->pick_event.crossing.y_root = event->button.y_root; 2458 } 2459 } else 2460 canvas->pick_event = *event; 2461 } 2462 2463 /* Don't do anything else if this is a recursive call */ 2464 2465 if (canvas->in_repick) 2466 return retval; 2467 2468 /* LeaveNotify means that there is no current item, so we don't look for one */ 2469 2470 if (canvas->pick_event.type != GDK_LEAVE_NOTIFY) { 2471 /* these fields don't have the same offsets in both types of events */ 2472 2473 if (canvas->pick_event.type == GDK_ENTER_NOTIFY) { 2474 x = canvas->pick_event.crossing.x - canvas->zoom_xofs; 2475 y = canvas->pick_event.crossing.y - canvas->zoom_yofs; 2476 } else { 2477 x = canvas->pick_event.motion.x - canvas->zoom_xofs; 2478 y = canvas->pick_event.motion.y - canvas->zoom_yofs; 2479 } 2480 2481 /* canvas pixel coords */ 2482 2483 cx = (gint) (x + 0.5); 2484 cy = (gint) (y + 0.5); 2485 2486 /* world coords */ 2487 2488 x = canvas->scroll_x1 + x; 2489 y = canvas->scroll_y1 + y; 2490 2491 /* find the closest item */ 2492 2493 if (canvas->root->flags & GNOME_CANVAS_ITEM_VISIBLE) 2494 canvas->new_current_item = 2495 gnome_canvas_item_invoke_point ( 2496 canvas->root, x, y, cx, cy); 2497 else 2498 canvas->new_current_item = NULL; 2499 } else 2500 canvas->new_current_item = NULL; 2501 2502 if ((canvas->new_current_item == canvas->current_item) 2503 && !canvas->left_grabbed_item) 2504 return retval; /* current item did not change */ 2505 2506 /* Synthesize events for old and new current items */ 2507 2508 if ((canvas->new_current_item != canvas->current_item) 2509 && (canvas->current_item != NULL) 2510 && !canvas->left_grabbed_item) { 2511 GdkEvent new_event; 2512 2513 new_event = canvas->pick_event; 2514 new_event.type = GDK_LEAVE_NOTIFY; 2515 2516 new_event.crossing.detail = GDK_NOTIFY_ANCESTOR; 2517 new_event.crossing.subwindow = NULL; 2518 canvas->in_repick = TRUE; 2519 retval = emit_event (canvas, &new_event); 2520 canvas->in_repick = FALSE; 2521 } 2522 2523 /* new_current_item may have been set to NULL during the 2524 * call to emit_event() above */ 2525 2526 if ((canvas->new_current_item != canvas->current_item) && button_down) { 2527 canvas->left_grabbed_item = TRUE; 2528 return retval; 2529 } 2530 2531 /* Handle the rest of cases */ 2532 2533 canvas->left_grabbed_item = FALSE; 2534 canvas->current_item = canvas->new_current_item; 2535 2536 if (canvas->current_item != NULL) { 2537 GdkEvent new_event; 2538 2539 new_event = canvas->pick_event; 2540 new_event.type = GDK_ENTER_NOTIFY; 2541 new_event.crossing.detail = GDK_NOTIFY_ANCESTOR; 2542 new_event.crossing.subwindow = NULL; 2543 retval = emit_event (canvas, &new_event); 2544 } 2545 2546 return retval; 2547 } 2548 2549 /* Button event handler for the canvas */ 2550 static gint 2551 gnome_canvas_button (GtkWidget *widget, 2552 GdkEventButton *event) 2553 { 2554 GnomeCanvas *canvas; 2555 GtkLayout *layout; 2556 GdkWindow *bin_window; 2557 gint mask; 2558 gint retval; 2559 2560 g_return_val_if_fail (GNOME_IS_CANVAS (widget), FALSE); 2561 g_return_val_if_fail (event != NULL, FALSE); 2562 2563 retval = FALSE; 2564 2565 canvas = GNOME_CANVAS (widget); 2566 2567 layout = GTK_LAYOUT (canvas); 2568 bin_window = gtk_layout_get_bin_window (layout); 2569 2570 /* 2571 * dispatch normally regardless of the event's window if an item has 2572 * has a pointer grab in effect 2573 */ 2574 if (!canvas->grabbed_item && event->window != bin_window) 2575 return retval; 2576 2577 switch (event->button) { 2578 case 1: 2579 mask = GDK_BUTTON1_MASK; 2580 break; 2581 case 2: 2582 mask = GDK_BUTTON2_MASK; 2583 break; 2584 case 3: 2585 mask = GDK_BUTTON3_MASK; 2586 break; 2587 case 4: 2588 mask = GDK_BUTTON4_MASK; 2589 break; 2590 case 5: 2591 mask = GDK_BUTTON5_MASK; 2592 break; 2593 default: 2594 mask = 0; 2595 } 2596 2597 switch (event->type) { 2598 case GDK_BUTTON_PRESS: 2599 case GDK_2BUTTON_PRESS: 2600 case GDK_3BUTTON_PRESS: 2601 /* Pick the current item as if the button were not pressed, and 2602 * then process the event. 2603 */ 2604 canvas->state = event->state; 2605 pick_current_item (canvas, (GdkEvent *) event); 2606 canvas->state ^= mask; 2607 retval = emit_event (canvas, (GdkEvent *) event); 2608 break; 2609 2610 case GDK_BUTTON_RELEASE: 2611 /* Process the event as if the button were pressed, then repick 2612 * after the button has been released 2613 */ 2614 canvas->state = event->state; 2615 retval = emit_event (canvas, (GdkEvent *) event); 2616 event->state ^= mask; 2617 canvas->state = event->state; 2618 pick_current_item (canvas, (GdkEvent *) event); 2619 event->state ^= mask; 2620 break; 2621 2622 default: 2623 g_warn_if_reached (); 2624 } 2625 2626 return retval; 2627 } 2628 2629 /* Motion event handler for the canvas */ 2630 static gint 2631 gnome_canvas_motion (GtkWidget *widget, 2632 GdkEventMotion *event) 2633 { 2634 GnomeCanvas *canvas; 2635 GtkLayout *layout; 2636 GdkWindow *bin_window; 2637 2638 g_return_val_if_fail (GNOME_IS_CANVAS (widget), FALSE); 2639 g_return_val_if_fail (event != NULL, FALSE); 2640 2641 canvas = GNOME_CANVAS (widget); 2642 2643 layout = GTK_LAYOUT (widget); 2644 bin_window = gtk_layout_get_bin_window (layout); 2645 2646 if (event->window != bin_window) 2647 return FALSE; 2648 2649 canvas->state = event->state; 2650 pick_current_item (canvas, (GdkEvent *) event); 2651 return emit_event (canvas, (GdkEvent *) event); 2652 } 2653 2654 /* Key event handler for the canvas */ 2655 static gboolean 2656 gnome_canvas_key (GtkWidget *widget, 2657 GdkEventKey *event) 2658 { 2659 GnomeCanvas *canvas; 2660 2661 g_return_val_if_fail (GNOME_IS_CANVAS (widget), FALSE); 2662 g_return_val_if_fail (event != NULL, FALSE); 2663 2664 canvas = GNOME_CANVAS (widget); 2665 2666 if (!emit_event (canvas, (GdkEvent *) event)) { 2667 GtkWidgetClass *widget_class; 2668 2669 widget_class = GTK_WIDGET_CLASS (gnome_canvas_parent_class); 2670 2671 if (event->type == GDK_KEY_PRESS) { 2672 if (widget_class->key_press_event) 2673 return (* widget_class->key_press_event) (widget, event); 2674 } else if (event->type == GDK_KEY_RELEASE) { 2675 if (widget_class->key_release_event) 2676 return (* widget_class->key_release_event) (widget, event); 2677 } else 2678 g_warn_if_reached (); 2679 2680 return FALSE; 2681 } else 2682 return TRUE; 2683 } 2684 2685 /* Crossing event handler for the canvas */ 2686 static gint 2687 gnome_canvas_crossing (GtkWidget *widget, 2688 GdkEventCrossing *event) 2689 { 2690 GnomeCanvas *canvas; 2691 GtkLayout *layout; 2692 GdkWindow *bin_window; 2693 2694 g_return_val_if_fail (GNOME_IS_CANVAS (widget), FALSE); 2695 g_return_val_if_fail (event != NULL, FALSE); 2696 2697 canvas = GNOME_CANVAS (widget); 2698 2699 layout = GTK_LAYOUT (canvas); 2700 bin_window = gtk_layout_get_bin_window (layout); 2701 2702 if (event->window != bin_window) 2703 return FALSE; 2704 2705 /* XXX Detect and disregard synthesized crossing events generated 2706 * by synth_crossing() in gtkwidget.c. The pointer coordinates 2707 * are invalid and pick_current_item() relies on them. */ 2708 if (event->x == 0 && event->y == 0 && 2709 event->x_root == 0 && event->y_root == 0) 2710 return FALSE; 2711 2712 canvas->state = event->state; 2713 return pick_current_item (canvas, (GdkEvent *) event); 2714 } 2715 2716 /* Focus in handler for the canvas */ 2717 static gint 2718 gnome_canvas_focus_in (GtkWidget *widget, 2719 GdkEventFocus *event) 2720 { 2721 GnomeCanvas *canvas; 2722 2723 /* XXX Can't access flags directly anymore, but is it really needed? 2724 * If so, could we call gtk_widget_send_focus_change() instead? */ 2725 #if 0 2726 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS); 2727 #endif 2728 2729 canvas = GNOME_CANVAS (widget); 2730 2731 if (canvas->focused_item) 2732 return emit_event (canvas, (GdkEvent *) event); 2733 else 2734 return FALSE; 2735 } 2736 2737 /* Focus out handler for the canvas */ 2738 static gint 2739 gnome_canvas_focus_out (GtkWidget *widget, 2740 GdkEventFocus *event) 2741 { 2742 GnomeCanvas *canvas; 2743 2744 /* XXX Can't access flags directly anymore, but is it really needed? 2745 * If so, could we call gtk_widget_send_focus_change() instead? */ 2746 #if 0 2747 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS); 2748 #endif 2749 2750 canvas = GNOME_CANVAS (widget); 2751 2752 if (canvas->focused_item) 2753 return emit_event (canvas, (GdkEvent *) event); 2754 else 2755 return FALSE; 2756 } 2757 2758 static void 2759 gnome_canvas_draw_background (GnomeCanvas *canvas, 2760 cairo_t *cr, 2761 gint x, 2762 gint y, 2763 gint width, 2764 gint height) 2765 { 2766 GtkStyle *style; 2767 2768 style = gtk_widget_get_style (GTK_WIDGET (canvas)); 2769 2770 cairo_save (cr); 2771 gdk_cairo_set_source_color (cr, &style->bg[GTK_STATE_NORMAL]); 2772 cairo_paint (cr); 2773 cairo_restore (cr); 2774 } 2775 2776 static void 2777 do_update (GnomeCanvas *canvas) 2778 { 2779 /* Cause the update if necessary */ 2780 2781 update_again: 2782 if (canvas->need_update) { 2783 cairo_matrix_t w2c; 2784 2785 /* We start updating root with w2c matrix */ 2786 gnome_canvas_w2c_matrix (canvas, &w2c); 2787 2788 gnome_canvas_item_invoke_update (canvas->root, &w2c, 0); 2789 2790 canvas->need_update = FALSE; 2791 } 2792 2793 /* Pick new current item */ 2794 2795 while (canvas->need_repick) { 2796 canvas->need_repick = FALSE; 2797 pick_current_item (canvas, &canvas->pick_event); 2798 } 2799 2800 /* it is possible that during picking we emitted an event in which 2801 * the user then called some function which then requested update 2802 * of something. Without this we'd be left in a state where 2803 * need_update would have been left TRUE and the canvas would have 2804 * been left unpainted. */ 2805 if (canvas->need_update) { 2806 goto update_again; 2807 } 2808 } 2809 2810 /* Idle handler for the canvas. It deals with pending updates and redraws. */ 2811 static gboolean 2812 idle_handler (gpointer data) 2813 { 2814 GnomeCanvas *canvas; 2815 2816 canvas = GNOME_CANVAS (data); 2817 2818 do_update (canvas); 2819 2820 /* Reset idle id */ 2821 canvas->idle_id = 0; 2822 2823 return FALSE; 2824 } 2825 2826 /* Convenience function to add an idle handler to a canvas */ 2827 static void 2828 add_idle (GnomeCanvas *canvas) 2829 { 2830 g_return_if_fail (canvas->need_update); 2831 2832 if (!canvas->idle_id) 2833 canvas->idle_id = g_idle_add_full ( 2834 CANVAS_IDLE_PRIORITY, 2835 idle_handler, 2836 canvas, 2837 NULL); 2838 2839 /* canvas->idle_id = gtk_idle_add (idle_handler, canvas); */ 2840 } 2841 2842 /** 2843 * gnome_canvas_root: 2844 * @canvas: A canvas. 2845 * 2846 * Queries the root group of a canvas. 2847 * 2848 * Return value: The root group of the specified canvas. 2849 **/ 2850 GnomeCanvasGroup * 2851 gnome_canvas_root (GnomeCanvas *canvas) 2852 { 2853 g_return_val_if_fail (GNOME_IS_CANVAS (canvas), NULL); 2854 2855 return GNOME_CANVAS_GROUP (canvas->root); 2856 } 2857 2858 /** 2859 * gnome_canvas_set_scroll_region: 2860 * @canvas: A canvas. 2861 * @x1: Leftmost limit of the scrolling region. 2862 * @y1: Upper limit of the scrolling region. 2863 * @x2: Rightmost limit of the scrolling region. 2864 * @y2: Lower limit of the scrolling region. 2865 * 2866 * Sets the scrolling region of a canvas to the specified rectangle. The canvas 2867 * will then be able to scroll only within this region. The view of the canvas 2868 * is adjusted as appropriate to display as much of the new region as possible. 2869 **/ 2870 void 2871 gnome_canvas_set_scroll_region (GnomeCanvas *canvas, 2872 gdouble x1, 2873 gdouble y1, 2874 gdouble x2, 2875 gdouble y2) 2876 { 2877 GtkScrollable *scrollable; 2878 GtkAdjustment *hadjustment; 2879 GtkAdjustment *vadjustment; 2880 gdouble hadjustment_value; 2881 gdouble vadjustment_value; 2882 gdouble wxofs, wyofs; 2883 gint xofs, yofs; 2884 2885 g_return_if_fail (GNOME_IS_CANVAS (canvas)); 2886 2887 scrollable = GTK_SCROLLABLE (canvas); 2888 hadjustment = gtk_scrollable_get_hadjustment (scrollable); 2889 vadjustment = gtk_scrollable_get_vadjustment (scrollable); 2890 2891 hadjustment_value = gtk_adjustment_get_value (hadjustment); 2892 vadjustment_value = gtk_adjustment_get_value (vadjustment); 2893 2894 /* 2895 * Set the new scrolling region. If possible, do not move the 2896 * visible contents of the canvas. 2897 */ 2898 2899 gnome_canvas_c2w ( 2900 canvas, 2901 hadjustment_value + canvas->zoom_xofs, 2902 vadjustment_value + canvas->zoom_yofs, 2903 &wxofs, &wyofs); 2904 2905 canvas->scroll_x1 = x1; 2906 canvas->scroll_y1 = y1; 2907 canvas->scroll_x2 = x2; 2908 canvas->scroll_y2 = y2; 2909 2910 gnome_canvas_w2c (canvas, wxofs, wyofs, &xofs, &yofs);
Function call argument is an uninitialized value
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

Function call argument is an uninitialized value
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

2911 2912 scroll_to (canvas, xofs, yofs);
Function call argument is an uninitialized value
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

Function call argument is an uninitialized value
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

2913 2914 canvas->need_repick = TRUE; 2915 #if 0 2916 /* todo: should be requesting update */ 2917 (* GNOME_CANVAS_ITEM_CLASS (canvas->root->object.class)->update) ( 2918 canvas->root, NULL, NULL, 0); 2919 #endif 2920 } 2921 2922 /** 2923 * gnome_canvas_get_scroll_region: 2924 * @canvas: A canvas. 2925 * @x1: Leftmost limit of the scrolling region (return value). 2926 * @y1: Upper limit of the scrolling region (return value). 2927 * @x2: Rightmost limit of the scrolling region (return value). 2928 * @y2: Lower limit of the scrolling region (return value). 2929 * 2930 * Queries the scrolling region of a canvas. 2931 **/ 2932 void 2933 gnome_canvas_get_scroll_region (GnomeCanvas *canvas, 2934 gdouble *x1, 2935 gdouble *y1, 2936 gdouble *x2, 2937 gdouble *y2) 2938 { 2939 g_return_if_fail (GNOME_IS_CANVAS (canvas)); 2940 2941 if (x1) 2942 *x1 = canvas->scroll_x1; 2943 2944 if (y1) 2945 *y1 = canvas->scroll_y1; 2946 2947 if (x2) 2948 *x2 = canvas->scroll_x2; 2949 2950 if (y2) 2951 *y2 = canvas->scroll_y2; 2952 } 2953 2954 /** 2955 * gnome_canvas_scroll_to: 2956 * @canvas: A canvas. 2957 * @cx: Horizontal scrolling offset in canvas pixel units. 2958 * @cy: Vertical scrolling offset in canvas pixel units. 2959 * 2960 * Makes a canvas scroll to the specified offsets, given in canvas pixel units. 2961 * The canvas will adjust the view so that it is not outside the scrolling 2962 * region. This function is typically not used, as it is better to hook 2963 * scrollbars to the canvas layout's scrolling adjusments. 2964 **/ 2965 void 2966 gnome_canvas_scroll_to (GnomeCanvas *canvas, 2967 gint cx, 2968 gint cy) 2969 { 2970 g_return_if_fail (GNOME_IS_CANVAS (canvas)); 2971 2972 scroll_to (canvas, cx, cy); 2973 } 2974 2975 /** 2976 * gnome_canvas_get_scroll_offsets: 2977 * @canvas: A canvas. 2978 * @cx: Horizontal scrolling offset (return value). 2979 * @cy: Vertical scrolling offset (return value). 2980 * 2981 * Queries the scrolling offsets of a canvas. The values are returned in canvas 2982 * pixel units. 2983 **/ 2984 void 2985 gnome_canvas_get_scroll_offsets (GnomeCanvas *canvas, 2986 gint *cx, 2987 gint *cy) 2988 { 2989 GtkAdjustment *adjustment; 2990 GtkScrollable *scrollable; 2991 2992 g_return_if_fail (GNOME_IS_CANVAS (canvas)); 2993 2994 scrollable = GTK_SCROLLABLE (canvas); 2995 2996 if (cx) { 2997 adjustment = gtk_scrollable_get_hadjustment (scrollable); 2998 *cx = (gint) gtk_adjustment_get_value (adjustment); 2999 } 3000 3001 if (cy) { 3002 adjustment = gtk_scrollable_get_vadjustment (scrollable); 3003 *cy = (gint) gtk_adjustment_get_value (adjustment); 3004 } 3005 } 3006 3007 /** 3008 * gnome_canvas_get_item_at: 3009 * @canvas: A canvas. 3010 * @x: X position in world coordinates. 3011 * @y: Y position in world coordinates. 3012 * 3013 * Looks for the item that is under the specified position, which must be 3014 * specified in world coordinates. 3015 * 3016 * Return value: The sought item, or NULL if no item is at the specified 3017 * coordinates. 3018 **/ 3019 GnomeCanvasItem * 3020 gnome_canvas_get_item_at (GnomeCanvas *canvas, 3021 gdouble x, 3022 gdouble y) 3023 { 3024 gint cx, cy; 3025 3026 g_return_val_if_fail (GNOME_IS_CANVAS (canvas), NULL); 3027 3028 gnome_canvas_w2c (canvas, x, y, &cx, &cy); 3029 3030 return gnome_canvas_item_invoke_point (canvas->root, x, y, cx, cy);
Function call argument is an uninitialized value
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

Function call argument is an uninitialized value
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

3031 } 3032 3033 /* Queues an update of the canvas */ 3034 static void 3035 gnome_canvas_request_update (GnomeCanvas *canvas) 3036 { 3037 GNOME_CANVAS_GET_CLASS (canvas)->request_update (canvas); 3038 } 3039 3040 static void 3041 gnome_canvas_request_update_real (GnomeCanvas *canvas) 3042 { 3043 if (canvas->need_update) 3044 return; 3045 3046 canvas->need_update = TRUE; 3047 if (gtk_widget_get_mapped ((GtkWidget *) canvas)) 3048 add_idle (canvas); 3049 } 3050 3051 static inline void 3052 get_visible_rect (GnomeCanvas *canvas, 3053 GdkRectangle *visible) 3054 { 3055 GtkAllocation allocation; 3056 GtkScrollable *scrollable; 3057 GtkAdjustment *hadjustment; 3058 GtkAdjustment *vadjustment; 3059 gdouble hadjustment_value; 3060 gdouble vadjustment_value; 3061 3062 gtk_widget_get_allocation (GTK_WIDGET (canvas), &allocation); 3063 3064 scrollable = GTK_SCROLLABLE (canvas); 3065 hadjustment = gtk_scrollable_get_hadjustment (scrollable); 3066 vadjustment = gtk_scrollable_get_vadjustment (scrollable); 3067 3068 hadjustment_value = gtk_adjustment_get_value (hadjustment); 3069 vadjustment_value = gtk_adjustment_get_value (vadjustment); 3070 3071 visible->x = hadjustment_value - canvas->zoom_xofs; 3072 visible->y = vadjustment_value - canvas->zoom_yofs; 3073 visible->width = allocation.width; 3074 visible->height = allocation.height; 3075 } 3076 3077 /** 3078 * gnome_canvas_request_redraw: 3079 * @canvas: A canvas. 3080 * @x1: Leftmost coordinate of the rectangle to be redrawn. 3081 * @y1: Upper coordinate of the rectangle to be redrawn. 3082 * @x2: Rightmost coordinate of the rectangle to be redrawn, plus 1. 3083 * @y2: Lower coordinate of the rectangle to be redrawn, plus 1. 3084 * 3085 * Convenience function that informs a canvas that the specified rectangle needs 3086 * to be repainted. The rectangle includes @x1 and @y1, but not @x2 and @y2. To 3087 * be used only by item implementations. 3088 **/ 3089 void 3090 gnome_canvas_request_redraw (GnomeCanvas *canvas, 3091 gint x1, 3092 gint y1, 3093 gint x2, 3094 gint y2) 3095 { 3096 GdkRectangle area, clip; 3097 3098 g_return_if_fail (GNOME_IS_CANVAS (canvas)); 3099 3100 if (!gtk_widget_is_drawable (GTK_WIDGET (canvas)) || (x1 >= x2) || (y1 >= y2)) 3101 return; 3102 3103 area.x = x1; 3104 area.y = y1; 3105 area.width = x2 - x1 + 1; 3106 area.height = y2 - y1 + 1; 3107 3108 get_visible_rect (canvas, &clip); 3109 if (!gdk_rectangle_intersect (&area, &clip, &area)) 3110 return; 3111 3112 gdk_window_invalidate_rect ( 3113 gtk_layout_get_bin_window (GTK_LAYOUT (canvas)), 3114 &area, FALSE); 3115 } 3116 3117 /** 3118 * gnome_canvas_w2c_matrix: 3119 * @canvas: A canvas. 3120 * @matrix: (out): matrix to initialize 3121 * 3122 * Gets the transformtion matrix that converts from world coordinates to canvas 3123 * pixel coordinates. 3124 **/ 3125 void 3126 gnome_canvas_w2c_matrix (GnomeCanvas *canvas, 3127 cairo_matrix_t *matrix) 3128 { 3129 g_return_if_fail (GNOME_IS_CANVAS (canvas)); 3130 g_return_if_fail (matrix != NULL); 3131 3132 cairo_matrix_init_translate ( 3133 matrix, -canvas->scroll_x1, -canvas->scroll_y1); 3134 } 3135 3136 /** 3137 * gnome_canvas_c2w_matrix: 3138 * @canvas: A canvas. 3139 * @matrix: (out): matrix to initialize 3140 * 3141 * Gets the transformtion matrix that converts from canvas pixel coordinates to 3142 * world coordinates. 3143 **/ 3144 void 3145 gnome_canvas_c2w_matrix (GnomeCanvas *canvas, 3146 cairo_matrix_t *matrix) 3147 { 3148 g_return_if_fail (GNOME_IS_CANVAS (canvas)); 3149 g_return_if_fail (matrix != NULL); 3150 3151 cairo_matrix_init_translate ( 3152 matrix, canvas->scroll_x1, canvas->scroll_y1); 3153 } 3154 3155 /** 3156 * gnome_canvas_w2c: 3157 * @canvas: A canvas. 3158 * @wx: World X coordinate. 3159 * @wy: World Y coordinate. 3160 * @cx: X pixel coordinate (return value). 3161 * @cy: Y pixel coordinate (return value). 3162 * 3163 * Converts world coordinates into canvas pixel coordinates. 3164 **/ 3165 void 3166 gnome_canvas_w2c (GnomeCanvas *canvas, 3167 gdouble wx, 3168 gdouble wy, 3169 gint *cx, 3170 gint *cy) 3171 { 3172 cairo_matrix_t w2c; 3173 3174 g_return_if_fail (GNOME_IS_CANVAS (canvas)); 3175 3176 gnome_canvas_w2c_matrix (canvas, &w2c); 3177 cairo_matrix_transform_point (&w2c, &wx, &wy); 3178 3179 if (cx) 3180 *cx = floor (wx + 0.5); 3181 if (cy) 3182 *cy = floor (wy + 0.5); 3183 } 3184 3185 /** 3186 * gnome_canvas_w2c_d: 3187 * @canvas: A canvas. 3188 * @wx: World X coordinate. 3189 * @wy: World Y coordinate. 3190 * @cx: X pixel coordinate (return value). 3191 * @cy: Y pixel coordinate (return value). 3192 * 3193 * Converts world coordinates into canvas pixel coordinates. This 3194 * version returns coordinates in floating point coordinates, for 3195 * greater precision. 3196 **/ 3197 void 3198 gnome_canvas_w2c_d (GnomeCanvas *canvas, 3199 gdouble wx, 3200 gdouble wy, 3201 gdouble *cx, 3202 gdouble *cy) 3203 { 3204 cairo_matrix_t w2c; 3205 3206 g_return_if_fail (GNOME_IS_CANVAS (canvas)); 3207 3208 gnome_canvas_w2c_matrix (canvas, &w2c); 3209 cairo_matrix_transform_point (&w2c, &wx, &wy); 3210 3211 if (cx) 3212 *cx = wx; 3213 if (cy) 3214 *cy = wy; 3215 } 3216 3217 /** 3218 * gnome_canvas_c2w: 3219 * @canvas: A canvas. 3220 * @cx: Canvas pixel X coordinate. 3221 * @cy: Canvas pixel Y coordinate. 3222 * @wx: X world coordinate (return value). 3223 * @wy: Y world coordinate (return value). 3224 * 3225 * Converts canvas pixel coordinates to world coordinates. 3226 **/ 3227 void 3228 gnome_canvas_c2w (GnomeCanvas *canvas, 3229 gint cx, 3230 gint cy, 3231 gdouble *wx, 3232 gdouble *wy) 3233 { 3234 cairo_matrix_t c2w; 3235 gdouble x, y; 3236 3237 g_return_if_fail (GNOME_IS_CANVAS (canvas)); 3238 3239 x = cx; 3240 y = cy; 3241 gnome_canvas_c2w_matrix (canvas, &c2w); 3242 cairo_matrix_transform_point (&c2w, &x, &y); 3243 3244 if (wx) 3245 *wx = x; 3246 if (wy) 3247 *wy = y; 3248 } 3249 3250 /** 3251 * gnome_canvas_window_to_world: 3252 * @canvas: A canvas. 3253 * @winx: Window-relative X coordinate. 3254 * @winy: Window-relative Y coordinate. 3255 * @worldx: X world coordinate (return value). 3256 * @worldy: Y world coordinate (return value). 3257 * 3258 * Converts window-relative coordinates into world coordinates. You can use 3259 * this when you need to convert mouse coordinates into world coordinates, for 3260 * example. 3261 **/ 3262 void 3263 gnome_canvas_window_to_world (GnomeCanvas *canvas, 3264 gdouble winx, 3265 gdouble winy, 3266 gdouble *worldx, 3267 gdouble *worldy) 3268 { 3269 g_return_if_fail (GNOME_IS_CANVAS (canvas)); 3270 3271 if (worldx) 3272 *worldx = canvas->scroll_x1 + (winx - canvas->zoom_xofs); 3273 3274 if (worldy) 3275 *worldy = canvas->scroll_y1 + (winy - canvas->zoom_yofs); 3276 } 3277 3278 /** 3279 * gnome_canvas_world_to_window: 3280 * @canvas: A canvas. 3281 * @worldx: World X coordinate. 3282 * @worldy: World Y coordinate. 3283 * @winx: X window-relative coordinate. 3284 * @winy: Y window-relative coordinate. 3285 * 3286 * Converts world coordinates into window-relative coordinates. 3287 **/ 3288 void 3289 gnome_canvas_world_to_window (GnomeCanvas *canvas, 3290 gdouble worldx, 3291 gdouble worldy, 3292 gdouble *winx, 3293 gdouble *winy) 3294 { 3295 g_return_if_fail (GNOME_IS_CANVAS (canvas)); 3296 3297 if (winx) 3298 *winx = (worldx - canvas->scroll_x1) + canvas->zoom_xofs; 3299 3300 if (winy) 3301 *winy = (worldy - canvas->scroll_y1) + canvas->zoom_yofs; 3302 } 3303 3304 static gboolean 3305 boolean_handled_accumulator (GSignalInvocationHint *ihint, 3306 GValue *return_accu, 3307 const GValue *handler_return, 3308 gpointer dummy) 3309 { 3310 gboolean continue_emission; 3311 gboolean signal_handled; 3312 3313 signal_handled = g_value_get_boolean (handler_return); 3314 g_value_set_boolean (return_accu, signal_handled); 3315 continue_emission = !signal_handled; 3316 3317 return continue_emission; 3318 } 3319 3320 /* Class initialization function for GnomeCanvasItemClass */ 3321 static void 3322 gnome_canvas_item_class_init (GnomeCanvasItemClass *class) 3323 { 3324 GObjectClass *gobject_class; 3325 3326 gobject_class = (GObjectClass *) class; 3327 3328 gobject_class->set_property = gnome_canvas_item_set_property; 3329 gobject_class->get_property = gnome_canvas_item_get_property; 3330 3331 g_object_class_install_property ( 3332 gobject_class, 3333 ITEM_PROP_PARENT, 3334 g_param_spec_object ( 3335 "parent", 3336 NULL, 3337 NULL, 3338 GNOME_TYPE_CANVAS_ITEM, 3339 G_PARAM_READABLE | 3340 G_PARAM_WRITABLE)); 3341 3342 item_signals[ITEM_EVENT] = g_signal_new ( 3343 "event", 3344 G_TYPE_FROM_CLASS (class), 3345 G_SIGNAL_RUN_LAST, 3346 G_STRUCT_OFFSET (GnomeCanvasItemClass, event), 3347 boolean_handled_accumulator, NULL, NULL, 3348 G_TYPE_BOOLEAN, 1, 3349 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); 3350 3351 gobject_class->dispose = gnome_canvas_item_dispose; 3352 3353 class->update = gnome_canvas_item_update; 3354 class->realize = gnome_canvas_item_realize; 3355 class->unrealize = gnome_canvas_item_unrealize; 3356 class->map = gnome_canvas_item_map; 3357 class->unmap = gnome_canvas_item_unmap; 3358 class->dispose = gnome_canvas_item_dispose_item; 3359 }