Mercurial > MadButterfly
comparison src/redraw_man.c @ 224:29e1b2bffe4c
X backend only sent EVT_MOUSE_MOVE_RAW to MadButterfly.
- backend does not interpret mouse events (over/out/move), now.
- redraw manager, now, interpret mouse events to make it backend independent.
- The task (interpret mouse events) should be moved to somewhere in futhure.
- backend only sent MotionNotify as EVT_MOUSE_MOVE_RAW.
- EVT_MOUSE_MOVE_RAW is interpreted by backend independent code.
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Mon, 15 Dec 2008 10:13:03 +0800 |
parents | c234ee745ceb |
children | 2637519e2bd7 |
comparison
equal
deleted
inserted
replaced
223:8be36a0d4239 | 224:29e1b2bffe4c |
---|---|
5 #include "mb_types.h" | 5 #include "mb_types.h" |
6 #include "mb_shapes.h" | 6 #include "mb_shapes.h" |
7 #include "mb_tools.h" | 7 #include "mb_tools.h" |
8 #include "mb_redraw_man.h" | 8 #include "mb_redraw_man.h" |
9 #include "mb_observer.h" | 9 #include "mb_observer.h" |
10 | 10 #include "mb_prop.h" |
11 | |
12 #ifndef ASSERT | |
13 #define ASSERT(x) | |
14 #endif | |
11 | 15 |
12 /* NOTE: bounding box should also consider width of stroke. | 16 /* NOTE: bounding box should also consider width of stroke. |
13 */ | 17 */ |
14 | 18 |
15 #define sh_attach_geo(sh, g) \ | 19 #define sh_attach_geo(sh, g) \ |
233 | 237 |
234 RM_MEMBER(coord, geo); | 238 RM_MEMBER(coord, geo); |
235 coord->num_members--; | 239 coord->num_members--; |
236 } | 240 } |
237 | 241 |
242 static void mouse_event_root_dummy(event_t *evt, void *arg) { | |
243 } | |
244 | |
245 static void mouse_event_interpreter(event_t *evt, void *arg) { | |
246 mouse_event_t *mevt = (mouse_event_t *)evt; | |
247 redraw_man_t *rdman = (redraw_man_t *)arg; | |
248 mb_obj_t *obj; | |
249 mouse_event_t new_evt; | |
250 coord_t *coord; | |
251 shape_t *shape; | |
252 | |
253 ASSERT(evt->type == EVT_MOUSE_MOVE_RAW); | |
254 | |
255 obj = (mb_obj_t *)subject_get_object(evt->cur_tgt); | |
256 if(rdman->last_mouse_over == obj) { | |
257 evt->type = EVT_MOUSE_MOVE; | |
258 return; | |
259 } | |
260 | |
261 new_evt.x = mevt->x; | |
262 new_evt.y = mevt->y; | |
263 new_evt.but_state = mevt->but_state; | |
264 new_evt.button = mevt->button; | |
265 | |
266 if(rdman->last_mouse_over != NULL) { | |
267 new_evt.event.type = EVT_MOUSE_OUT; | |
268 if(IS_MBO_COORD(rdman->last_mouse_over)) { | |
269 coord = (coord_t *)rdman->last_mouse_over; | |
270 subject_notify(coord->mouse_event, (event_t *)&new_evt); | |
271 } else if(IS_MBO_SHAPES(rdman->last_mouse_over)) { | |
272 shape = (shape_t *)rdman->last_mouse_over; | |
273 ASSERT(shape->geo != NULL); | |
274 subject_notify(shape->geo->mouse_event, (event_t *)&new_evt); | |
275 } | |
276 } | |
277 | |
278 new_evt.event.type = EVT_MOUSE_OVER; | |
279 subject_notify(evt->cur_tgt, (event_t *)&new_evt); | |
280 rdman->last_mouse_over = obj; | |
281 | |
282 evt->flags |= EVTF_STOP_NOTIFY; | |
283 } | |
284 | |
285 static void addrm_monitor_hdlr(event_t *evt, void *arg) { | |
286 monitor_event_t *mevt; | |
287 redraw_man_t *rdman; | |
288 mb_obj_t *obj; | |
289 mb_prop_store_t *props; | |
290 observer_t *observer; | |
291 int cnt = 0; | |
292 | |
293 mevt = (monitor_event_t *)evt; | |
294 rdman = (redraw_man_t *)evt->tgt; | |
295 obj = (mb_obj_t *)subject_get_object(mevt->subject); | |
296 props = mb_obj_prop_store(obj); | |
297 | |
298 switch(evt->type) { | |
299 case EVT_MONITOR_ADD: | |
300 if(!mb_prop_has(props, PROP_MEVT_OB_CNT)) | |
301 cnt = 0; | |
302 else | |
303 cnt = (int)mb_prop_get(props, PROP_MEVT_OB_CNT); | |
304 | |
305 cnt++; | |
306 mb_prop_set(props, PROP_MEVT_OB_CNT, (void *)cnt); | |
307 if(cnt == 1) { | |
308 observer = | |
309 subject_add_event_observer_head(mevt->subject, | |
310 EVT_MOUSE_MOVE_RAW, | |
311 mouse_event_interpreter, | |
312 rdman); | |
313 ASSERT(observer != NULL); | |
314 mb_prop_set(props, PROP_MEVT_OBSERVER, observer); | |
315 } | |
316 break; | |
317 | |
318 case EVT_MONITOR_REMOVE: | |
319 cnt = (int)mb_prop_get(props, PROP_MEVT_OB_CNT); | |
320 cnt--; | |
321 mb_prop_set(props, PROP_MEVT_OB_CNT, (void *)cnt); | |
322 if(cnt == 1) { | |
323 observer = (observer_t *)mb_prop_get(props, PROP_MEVT_OBSERVER); | |
324 subject_remove_observer(mevt->subject, observer); | |
325 mb_prop_del(props, PROP_MEVT_OBSERVER); | |
326 } | |
327 break; | |
328 | |
329 case EVT_MONITOR_FREE: | |
330 break; | |
331 } | |
332 } | |
333 | |
238 int redraw_man_init(redraw_man_t *rdman, cairo_t *cr, cairo_t *backend) { | 334 int redraw_man_init(redraw_man_t *rdman, cairo_t *cr, cairo_t *backend) { |
239 extern void redraw_man_destroy(redraw_man_t *rdman); | 335 extern void redraw_man_destroy(redraw_man_t *rdman); |
240 extern int _paint_color_size; | 336 extern int _paint_color_size; |
337 observer_t *addrm_ob; | |
241 | 338 |
242 memset(rdman, 0, sizeof(redraw_man_t)); | 339 memset(rdman, 0, sizeof(redraw_man_t)); |
243 | 340 |
244 rdman->geo_pool = elmpool_new(sizeof(geo_t), 128); | 341 rdman->geo_pool = elmpool_new(sizeof(geo_t), 128); |
245 if(rdman->geo_pool == NULL) | |
246 return ERR; | |
247 | |
248 rdman->coord_pool = elmpool_new(sizeof(coord_t), 16); | 342 rdman->coord_pool = elmpool_new(sizeof(coord_t), 16); |
249 if(rdman->coord_pool == NULL) { | |
250 elmpool_free(rdman->geo_pool); | |
251 return ERR; | |
252 } | |
253 | |
254 rdman->shnode_pool = elmpool_new(sizeof(shnode_t), 16); | 343 rdman->shnode_pool = elmpool_new(sizeof(shnode_t), 16); |
255 if(rdman->shnode_pool == NULL) { | |
256 elmpool_free(rdman->geo_pool); | |
257 elmpool_free(rdman->coord_pool); | |
258 return ERR; | |
259 } | |
260 | |
261 rdman->observer_pool = elmpool_new(sizeof(observer_t), 32); | 344 rdman->observer_pool = elmpool_new(sizeof(observer_t), 32); |
262 if(rdman->observer_pool == NULL) { | |
263 elmpool_free(rdman->geo_pool); | |
264 elmpool_free(rdman->coord_pool); | |
265 elmpool_free(rdman->shnode_pool); | |
266 return ERR; | |
267 } | |
268 | |
269 rdman->subject_pool = elmpool_new(sizeof(subject_t), 32); | 345 rdman->subject_pool = elmpool_new(sizeof(subject_t), 32); |
270 if(rdman->subject_pool == NULL) { | |
271 elmpool_free(rdman->geo_pool); | |
272 elmpool_free(rdman->coord_pool); | |
273 elmpool_free(rdman->shnode_pool); | |
274 elmpool_free(rdman->observer_pool); | |
275 return ERR; | |
276 } | |
277 | |
278 rdman->paint_color_pool = elmpool_new(_paint_color_size, 64); | 346 rdman->paint_color_pool = elmpool_new(_paint_color_size, 64); |
279 if(rdman->subject_pool == NULL) { | 347 rdman->pent_pool = elmpool_new(sizeof(mb_prop_entry_t), 128); |
280 elmpool_free(rdman->geo_pool); | 348 if(!(rdman->geo_pool && rdman->coord_pool && rdman->shnode_pool && |
281 elmpool_free(rdman->coord_pool); | 349 rdman->observer_pool && rdman->subject_pool && |
282 elmpool_free(rdman->shnode_pool); | 350 rdman->paint_color_pool)) |
283 elmpool_free(rdman->observer_pool); | 351 goto err; |
284 elmpool_free(rdman->subject_pool); | |
285 return ERR; | |
286 } | |
287 | 352 |
288 rdman->ob_factory.subject_alloc = ob_subject_alloc; | 353 rdman->ob_factory.subject_alloc = ob_subject_alloc; |
289 rdman->ob_factory.subject_free = ob_subject_free; | 354 rdman->ob_factory.subject_free = ob_subject_free; |
290 rdman->ob_factory.observer_alloc = ob_observer_alloc; | 355 rdman->ob_factory.observer_alloc = ob_observer_alloc; |
291 rdman->ob_factory.observer_free = ob_observer_free; | 356 rdman->ob_factory.observer_free = ob_observer_free; |
292 rdman->ob_factory.get_parent_subject = ob_get_parent_subject; | 357 rdman->ob_factory.get_parent_subject = ob_get_parent_subject; |
293 | 358 |
294 rdman->redraw = | 359 rdman->redraw = |
295 subject_new(&rdman->ob_factory, rdman, OBJT_RDMAN); | 360 subject_new(&rdman->ob_factory, rdman, OBJT_RDMAN); |
361 rdman->addrm_monitor = | |
362 subject_new(&rdman->ob_factory, rdman, OBJT_RDMAN); | |
363 if(!(rdman->redraw && rdman->addrm_monitor)) | |
364 goto err; | |
365 | |
366 addrm_ob = subject_add_observer(rdman->addrm_monitor, | |
367 addrm_monitor_hdlr, NULL); | |
368 if(addrm_ob == NULL) | |
369 goto err; | |
370 | |
371 rdman->last_mouse_over = NULL; | |
296 | 372 |
297 rdman->root_coord = elmpool_elm_alloc(rdman->coord_pool); | 373 rdman->root_coord = elmpool_elm_alloc(rdman->coord_pool); |
298 if(rdman->root_coord == NULL) | 374 if(rdman->root_coord == NULL) |
299 redraw_man_destroy(rdman); | 375 redraw_man_destroy(rdman); |
300 rdman->n_coords = 1; | 376 rdman->n_coords = 1; |
301 coord_init(rdman->root_coord, NULL); | 377 coord_init(rdman->root_coord, NULL); |
378 mb_prop_store_init(&rdman->root_coord->obj.props, rdman->pent_pool); | |
302 rdman->root_coord->mouse_event = subject_new(&rdman->ob_factory, | 379 rdman->root_coord->mouse_event = subject_new(&rdman->ob_factory, |
303 rdman->root_coord, | 380 rdman->root_coord, |
304 OBJT_COORD); | 381 OBJT_COORD); |
305 rdman->root_coord->flags |= COF_OWN_CANVAS; | 382 rdman->root_coord->flags |= COF_OWN_CANVAS; |
306 rdman->root_coord->canvas = cr; | 383 rdman->root_coord->canvas = cr; |
309 rdman->cr = cr; | 386 rdman->cr = cr; |
310 rdman->backend = backend; | 387 rdman->backend = backend; |
311 | 388 |
312 STAILQ_INIT(rdman->shapes); | 389 STAILQ_INIT(rdman->shapes); |
313 STAILQ_INIT(rdman->paints); | 390 STAILQ_INIT(rdman->paints); |
391 | |
392 /* \note To make root coord always have at leat one observer. | |
393 * It triggers mouse interpreter to be installed on root. | |
394 */ | |
395 subject_set_monitor(rdman->root_coord->mouse_event, | |
396 rdman->addrm_monitor); | |
397 subject_add_observer(rdman->root_coord->mouse_event, | |
398 mouse_event_root_dummy, NULL); | |
314 | 399 |
315 return OK; | 400 return OK; |
401 | |
402 err: | |
403 if(rdman->geo_pool) | |
404 elmpool_free(rdman->geo_pool); | |
405 if(rdman->coord_pool) | |
406 elmpool_free(rdman->coord_pool); | |
407 if(rdman->shnode_pool) | |
408 elmpool_free(rdman->shnode_pool); | |
409 if(rdman->observer_pool) | |
410 elmpool_free(rdman->observer_pool); | |
411 if(rdman->subject_pool) | |
412 elmpool_free(rdman->subject_pool); | |
413 if(rdman->paint_color_pool) | |
414 elmpool_free(rdman->paint_color_pool); | |
415 if(rdman->pent_pool) | |
416 elmpool_free(rdman->pent_pool); | |
417 return ERR; | |
316 } | 418 } |
317 | 419 |
318 void redraw_man_destroy(redraw_man_t *rdman) { | 420 void redraw_man_destroy(redraw_man_t *rdman) { |
319 coord_t *coord, *saved_coord; | 421 coord_t *coord, *saved_coord; |
320 shape_t *shape, *saved_shape; | 422 shape_t *shape, *saved_shape; |
330 FORMEMBERS(saved_coord, member) { | 432 FORMEMBERS(saved_coord, member) { |
331 rdman_shape_free(rdman, member->shape); | 433 rdman_shape_free(rdman, member->shape); |
332 } | 434 } |
333 rdman_coord_free(rdman, saved_coord); | 435 rdman_coord_free(rdman, saved_coord); |
334 } | 436 } |
437 #if 0 | |
335 FORMEMBERS(saved_coord, member) { | 438 FORMEMBERS(saved_coord, member) { |
336 rdman_shape_free(rdman, member->shape); | 439 rdman_shape_free(rdman, member->shape); |
337 } | 440 } |
441 #endif | |
338 /* Resources of root_coord is free by elmpool_free() or | 442 /* Resources of root_coord is free by elmpool_free() or |
339 * caller; for canvas | 443 * caller; for canvas |
340 */ | 444 */ |
341 | 445 |
342 shape = saved_shape = STAILQ_HEAD(rdman->shapes); | 446 shape = saved_shape = STAILQ_HEAD(rdman->shapes); |
354 elmpool_free(rdman->geo_pool); | 458 elmpool_free(rdman->geo_pool); |
355 elmpool_free(rdman->shnode_pool); | 459 elmpool_free(rdman->shnode_pool); |
356 elmpool_free(rdman->observer_pool); | 460 elmpool_free(rdman->observer_pool); |
357 elmpool_free(rdman->subject_pool); | 461 elmpool_free(rdman->subject_pool); |
358 elmpool_free(rdman->paint_color_pool); | 462 elmpool_free(rdman->paint_color_pool); |
463 elmpool_free(rdman->pent_pool); | |
359 | 464 |
360 DARRAY_DESTROY(&rdman->dirty_coords); | 465 DARRAY_DESTROY(&rdman->dirty_coords); |
361 DARRAY_DESTROY(&rdman->dirty_geos); | 466 DARRAY_DESTROY(&rdman->dirty_geos); |
362 DARRAY_DESTROY(&rdman->dirty_areas); | 467 DARRAY_DESTROY(&rdman->dirty_areas); |
363 DARRAY_DESTROY(&rdman->gen_geos); | 468 DARRAY_DESTROY(&rdman->gen_geos); |
395 if(geo == NULL) | 500 if(geo == NULL) |
396 return ERR; | 501 return ERR; |
397 | 502 |
398 geo_init(geo); | 503 geo_init(geo); |
399 geo->mouse_event = subject_new(&rdman->ob_factory, geo, OBJT_GEO); | 504 geo->mouse_event = subject_new(&rdman->ob_factory, geo, OBJT_GEO); |
505 subject_set_monitor(geo->mouse_event, rdman->addrm_monitor); | |
400 | 506 |
401 geo_attach_coord(geo, coord); | 507 geo_attach_coord(geo, coord); |
402 | 508 |
403 /* New one should be dirty to recompute it when drawing. */ | 509 /* New one should be dirty to recompute it when drawing. */ |
404 r = add_dirty_geo(rdman, geo); | 510 r = add_dirty_geo(rdman, geo); |
440 return ERR; | 546 return ERR; |
441 return OK; | 547 return OK; |
442 } | 548 } |
443 | 549 |
444 if(geo != NULL) { | 550 if(geo != NULL) { |
551 subject_free(geo->mouse_event); | |
445 geo_detach_coord(geo, shape->coord); | 552 geo_detach_coord(geo, shape->coord); |
446 sh_detach_coord(shape); | 553 sh_detach_coord(shape); |
447 sh_detach_geo(shape); | 554 sh_detach_geo(shape); |
448 subject_free(geo->mouse_event); | |
449 elmpool_elm_free(rdman->geo_pool, geo); | 555 elmpool_elm_free(rdman->geo_pool, geo); |
450 } | 556 } |
451 STAILQ_REMOVE(rdman->shapes, shape_t, sh_next, shape); | 557 STAILQ_REMOVE(rdman->shapes, shape_t, sh_next, shape); |
452 shape->free(shape); | 558 shape->free(shape); |
559 | |
560 if(rdman->last_mouse_over == (mb_obj_t *)shape) | |
561 rdman->last_mouse_over = NULL; | |
562 | |
453 return OK; | 563 return OK; |
454 } | 564 } |
455 | 565 |
456 shnode_t *shnode_new(redraw_man_t *rdman, shape_t *shape) { | 566 shnode_t *shnode_new(redraw_man_t *rdman, shape_t *shape) { |
457 shnode_t *node; | 567 shnode_t *node; |
515 coord = elmpool_elm_alloc(rdman->coord_pool); | 625 coord = elmpool_elm_alloc(rdman->coord_pool); |
516 if(coord == NULL) | 626 if(coord == NULL) |
517 return NULL; | 627 return NULL; |
518 | 628 |
519 coord_init(coord, parent); | 629 coord_init(coord, parent); |
630 mb_prop_store_init(&coord->obj.props, rdman->pent_pool); | |
520 coord->mouse_event = subject_new(&rdman->ob_factory, | 631 coord->mouse_event = subject_new(&rdman->ob_factory, |
521 coord, | 632 coord, |
522 OBJT_COORD); | 633 OBJT_COORD); |
634 subject_set_monitor(coord->mouse_event, rdman->addrm_monitor); | |
523 /*! \note default opacity == 1 */ | 635 /*! \note default opacity == 1 */ |
524 coord->opacity = 1; | 636 coord->opacity = 1; |
525 if(parent) | 637 if(parent) |
526 coord->canvas = parent->canvas; | 638 coord->canvas = parent->canvas; |
527 rdman->n_coords++; | 639 rdman->n_coords++; |
611 rdman->n_coords--; | 723 rdman->n_coords--; |
612 | 724 |
613 return OK; | 725 return OK; |
614 } | 726 } |
615 | 727 |
616 static _rdman_coord_free_members(redraw_man_t *rdman, coord_t *coord) { | 728 static int _rdman_coord_free_members(redraw_man_t *rdman, coord_t *coord) { |
617 geo_t *member; | 729 geo_t *member; |
618 shape_t *shape; | 730 shape_t *shape; |
619 int r; | 731 int r; |
620 | 732 |
621 FORMEMBERS(coord, member) { | 733 FORMEMBERS(coord, member) { |
1466 dummy->w = w; | 1578 dummy->w = w; |
1467 dummy->h = h; | 1579 dummy->h = h; |
1468 dummy->trans_cnt = 0; | 1580 dummy->trans_cnt = 0; |
1469 dummy->draw_cnt = 0; | 1581 dummy->draw_cnt = 0; |
1470 dummy->shape.free = sh_dummy_free; | 1582 dummy->shape.free = sh_dummy_free; |
1471 | 1583 |
1472 rdman_shape_man(rdman, (shape_t *)dummy); | 1584 rdman_shape_man(rdman, (shape_t *)dummy); |
1473 | 1585 |
1474 return (shape_t *)dummy; | 1586 return (shape_t *)dummy; |
1475 } | 1587 } |
1476 | 1588 |