Beispiel #1
0
/** 追加子部件 */
int $(Append)( LCUI_Widget container, LCUI_Widget widget )
{
	int i, n;
	LCUI_Widget old_container;
	LCUI_WidgetEvent e;
	DEBUG_MSG("container: %p, widget: %p\n", container, widget);
	if( !container || !widget || container == widget->parent ) {
		return -1;
	}
	if( container == widget ) {
		return -2;
	}
	if( widget->parent ) {
		old_container = widget->parent;
	} else {
		goto remove_done;
	}

	/* 移除在之前的容器中的记录 */
	n = LinkedList_GetTotal( &old_container->children );
	for( i=0; i<n; ++i ) {
		LinkedList_Goto( &old_container->children, i );
		if( LinkedList_Get(&old_container->children) == widget ) {
			LinkedList_Delete( &old_container->children );
			break;
		}
	}
	/* 如果是从根级部件中移出,则触发 WET_REMOVE 事件 */
	if( i < n && old_container == LCUIRootWidget ) {
		e.type_name = "TopLevelWidget";
		e.target = widget;
		Widget_PostEvent( LCUIRootWidget, &e, (int*)WET_REMOVE );
	}
	n = LinkedList_GetTotal( &old_container->children_show );
	for( i=0; i<n; ++i ) {
		LinkedList_Goto( &old_container->children_show, i );
		if( LinkedList_Get(&old_container->children_show) == widget ) {
			LinkedList_Delete( &old_container->children_show );
			break;
		}
	}

remove_done:

	widget->parent = container;
	LinkedList_AddData( &container->children, widget );
	LinkedList_AddData( &container->children_show, widget );
	/* 如果是添加至根部件内,则触发 WET_ADD 事件 */
	if( container == LCUIRootWidget ) {
		int ret;
		e.type_name = "TopLevelWidget";
		e.target = widget;
		ret = Widget_PostEvent( LCUIRootWidget, &e, (int*)WET_ADD );
		DEBUG_MSG("post done, ret = %d\n", ret);
	}
	Widget_UpdateTaskStatus( widget );
	DEBUG_MSG("tip\n");
	return 0;
}
Beispiel #2
0
/** 解除事件连接 */
int $(Unbind)( LCUI_EventBox box, int handler_id )
{
	int i, n;
	LCUI_RBTreeNode *node;
	LCUI_EventSlot *slot;
	LCUI_EventHandler *handler;

	if( !(node = RBTree_Search(&box->event_handler, handler_id)) ) {
		return -1;
	}
	if( !(node = RBTree_Search(&box->event_slot, (int)(node->data))) ) {
		return -2;
	}
	slot = (LCUI_EventSlot*)node->data;
	LinkedList_Goto( &slot->handlers, 0 );
	n = LinkedList_GetTotal( &slot->handlers );
	for( i=0; i<n; ++i ) {
		handler = (LCUI_EventHandler*)LinkedList_Get( &slot->handlers );
		if( handler->id == handler_id ) {
			LinkedList_Delete( &slot->handlers );
			RBTree_Erase( &box->event_handler, handler_id );
			return 0;
		}
		LinkedList_ToNext( &slot->handlers );
	}
	return -3;
}
Beispiel #3
0
/** 直接将事件发送至事件处理器进行处理 */
int $(Send)( LCUI_EventBox box, const char *name, void *data )
{
	int i, n;
	LCUI_Event event;
	LCUI_RBTreeNode *node;
	LCUI_EventSlot *slot;
	LCUI_EventHandler *handler;
	
	if( !(node = RBTree_CustomSearch(&box->event_name, (const void*)name)) ) {
		return -1;
	}
	if( !(node = RBTree_Search(&box->event_slot, node->key)) ) {
		return -2;
	}
	slot = (LCUI_EventSlot*)node->data;
	event.id = slot->id;
	event.name = slot->name;
	event.data = data;
	event.destroy_data = NULL;
	n = LinkedList_GetTotal( &slot->handlers );
	LinkedList_Goto( &slot->handlers, 0 );
	for( i=0; i<n; ++i ) {
		handler = (LCUI_EventHandler*)LinkedList_Get( &slot->handlers );
		handler->func( &event, handler->func_data );
		LinkedList_ToNext( &slot->handlers );
	}
	return 0;
}
Beispiel #4
0
/** 前置显示 */
int $(Front)( LCUI_Widget widget )
{
	int i, n, src_pos = -1, des_pos = -1;
	LCUI_Widget parent, child;

	parent = widget->parent ? widget->parent:LCUIRootWidget;
	n = LinkedList_GetTotal( &parent->children_show );
	/* 先在队列中找到自己,以及z-index值小于或等于它的第一个部件 */
	for( i=0; i<n; ++i ) {
		LinkedList_Goto( &parent->children_show, i );
		child = (LCUI_Widget)LinkedList_Get( &parent->children_show );
		if( child == widget ) {
			src_pos = i;
			continue;
		}
		if( des_pos >= 0 ) {
			if( src_pos >= 0 ) {
				break;
			}
			continue;
		}
		/* 如果该位置的图层的z-index值不大于自己 */
		if( child->style.z_index <= widget->style.z_index ) {
			/* 如果未找到自己的源位置 */
			if( src_pos == -1 ) {
				des_pos = i;
				continue;
			}
			/* 否则,退出循环,因为已经在前排了 */
			break;
		}
	}
	/* 没有找到就退出 */
	if( des_pos == -1 || src_pos == -1 ) {
		return -1;
	}
	/* 找到的话就移动位置 */
	LinkedList_Goto( &parent->children_show, src_pos );
	LinkedList_MoveTo( &parent->children_show, des_pos );
	// XXX
	return 0;
}
Beispiel #5
0
/** 更新各种图形元素的显示 */
static void LCUIDisplay_Update(void)
{
	int i, n, j, m;
	LCUI_Rect *p_rect;
	SurfaceRecord *p_sr;
	LCUI_DirtyRectList rlist;
	LCUI_PaintContext paint;

	DirtyRectList_Init( &rlist );
	n = LinkedList_GetTotal( &display.surfaces );
	/* 遍历当前的 surface 记录列表 */
	for( i=0; i<n; ++i ) {
		LinkedList_Goto( &display.surfaces, i );
		p_sr = (SurfaceRecord*)
		LinkedList_Get( &display.surfaces );
		if( !p_sr->widget || !p_sr->surface
		 || !Surface_IsReady(p_sr->surface) ) {
			continue;
		}
		/* 更新表面 */
		Surface_Update( p_sr->surface );
		/* 收集无效区域记录 */
		Widget_ProcInvalidArea( p_sr->widget, &rlist );
		m = LinkedList_GetTotal( &rlist );
		DEBUG_MSG("proc invalid area, m = %d\n", m);
		LinkedList_Goto( &rlist, 0 );
		/* 在 surface 上逐个重绘无效区域 */
		for( j=0; j<m; ++j ) {
			p_rect = (LCUI_Rect*)LinkedList_Get( &rlist );
			paint = Surface_BeginPaint( p_sr->surface, p_rect );
			DEBUG_MSG( "[%s]: render rect: (%d,%d,%d,%d), %d\n", p_sr->widget->type, paint->rect.left, paint->rect.top, paint->rect.w, paint->rect.h, j );
			Widget_Render( p_sr->widget, paint );
			Surface_EndPaint( p_sr->surface, paint );
			LinkedList_Delete( &rlist );
		}
		if( m > 0 ) {
			Surface_Present( p_sr->surface );
		}
	}

	LinkedList_Destroy( &rlist );
}
Beispiel #6
0
/** 派发当前待处理的事件至对应的处理器 */
int $(Dispatch)( LCUI_EventBox box )
{
	int i, n;
	LCUI_Event *e;
	LinkedList *elist;
	
	box->current = box->current ? 0:1;
	elist = &box->events[box->current ? 0:1];
	n = LinkedList_GetTotal( elist );
	LinkedList_Goto( elist, 0 );
	for( i=0; i<n; ++i ) {
		e = (LCUI_Event*)LinkedList_Get( elist );
		$(Send)( box, e->name, e->data );
		e->destroy_data ? e->destroy_data( e->data ):0;
		LinkedList_Goto( elist, 0 );
		LinkedList_Delete( elist );
	}
	box->current = box->current ? 0:1;
	return 0;
}
Beispiel #7
0
/** 获取当前的文本样式 */
LCUI_TextStyle* StyleTagStack_GetTextStyle( LCUI_StyleTagStack *tags )
{
	LCUI_StyleTagData *tag_data;
	LCUI_TextStyle *style_data;
	int i, total, equal = 0, flags[MAX_TAG_NUM];
	
	style_data = (LCUI_TextStyle*)malloc( sizeof(LCUI_TextStyle) );
	TextStyle_Init( style_data );
	memset( flags, 0, sizeof(flags) );
	
	total = LinkedList_GetTotal( tags );
	if(total <= 0) {
		free( style_data );
		return NULL;
	}
	/* 根据已经记录的各种样式,生成当前应有的文本样式 */
	for(equal=0,i=total-1; i>=0; --i) {
		LinkedList_Goto( tags, i );
		tag_data = (LCUI_StyleTagData*)LinkedList_Get( tags );
		DEBUG_MSG("tag id: %d\n", tag_data->tag_id);
		switch( tag_data->tag_id ) {
		    case TAG_ID_COLOR: 
			if( flags[0] != 0 ) {
				break;
			}
			style_data->_fore_color = TRUE;
			style_data->fore_color = tag_data->style.color;
			DEBUG_MSG("color: %d,%d,%d\n", data->fore_color.red,
			 data->fore_color.green, data->fore_color.blue);
			flags[0] = 1;
			++equal;
			break;
		case TAG_ID_SIZE:
			if( flags[1] != 0 ) {
				break;
			}
			style_data->_pixel_size = TRUE;
			style_data->pixel_size = tag_data->style.size.px;
			flags[1] = 1;
			++equal;
			break;
		    default: break;
		}
		if(equal == MAX_TAG_NUM) {
			break;
		}
	}
	if( equal == 0 ) {
		free( style_data );
		return NULL;
	}
	return style_data;
}
Beispiel #8
0
/** 派发当前待处理的事件至对应的处理器 */
int $(Dispatch)( LCUI_EventBox box )
{
	int i, n;
	LCUI_Event *e;
	LinkedList *elist;

	elist = &box->events[box->current];
	box->current = box->current ? 0:1;
	n = LinkedList_GetTotal( elist );
	LinkedList_Goto( elist, 0 );
	DEBUG_MSG("event total: %d\n", n);
	for( i=0; i<n; ++i ) {
		e = (LCUI_Event*)LinkedList_Get( elist );
		$(Send)( box, e->name, e->data );
		e->destroy_data ? e->destroy_data( e->data ):0;
		e->data = NULL;
		LinkedList_Goto( elist, 0 );
		LinkedList_Delete( elist );
	}
	DEBUG_MSG("quit\n");
	return 0;
}
Beispiel #9
0
static void LCUIDisplay_CleanSurfaces( void )
{
	int i, n;
	SurfaceRecord *p_sr;

	n = LinkedList_GetTotal( &display.surfaces );
	for( i=0; i<n; ++i ) {
		LinkedList_Goto( &display.surfaces, 0 );
		p_sr = (SurfaceRecord*)
		LinkedList_Get( &display.surfaces );
		Surface_Delete( p_sr->surface );
		LinkedList_Delete( &display.surfaces );
	}
}
Beispiel #10
0
/** 退出所有主循环 */
static void LCUIApp_QuitAllMainLoop(void)
{
	LCUI_MainLoop loop;
	int n = LinkedList_GetTotal( &MainApp.loop_list );
	LinkedList_Goto( &MainApp.loop_list, 0 );
	while( n-- ) {
		loop = (LCUI_MainLoop)LinkedList_Get( &MainApp.loop_list );
		if( !loop ) {
			break;
		}
		loop->state = STATE_EXITED;
		LinkedList_ToNext( &MainApp.loop_list );
	}
	LCUICond_Broadcast( &MainApp.loop_cond );
}
Beispiel #11
0
static LCUI_Surface LCUIDisplay_GetBindSurface( LCUI_Widget widget )
{
	int i, n;
	SurfaceRecord *p_sr;

	n = LinkedList_GetTotal( &display.surfaces );
	for( i=0; i<n; ++i ) {
		LinkedList_Goto( &display.surfaces, i );
		p_sr = (SurfaceRecord*)
		LinkedList_Get( &display.surfaces );
		if( p_sr->widget == widget ) {
			return p_sr->surface;
		}
	}
	return NULL;
}
Beispiel #12
0
/** 从已触发的事件记录中取出(不会移除)一个事件信息 */
int $(GetEvent)( LCUI_EventBox box, LCUI_Event *ebuff )
{
	int n;
	LCUI_Event *event;
	LinkedList *elist;
	
	elist = &box->events[box->current == 1 ? 0:1];
	n = LinkedList_GetTotal( elist );
	if( n <= 0 ) {
		return -1;
	}
	LinkedList_Goto( elist, 0 );
	event = (LCUI_Event*)LinkedList_Get( elist );
	*ebuff = *event;
	return 0;
}
Beispiel #13
0
/** 在 surface 主动产生无效区域的时候 */
static void OnInvalidRect( LCUI_Surface surface, LCUI_Rect *rect )
{
	int i, n;
	SurfaceRecord *p_sr;

	n = LinkedList_GetTotal( &display.surfaces );
	for( i=0; i<n; ++i ) {
		LinkedList_Goto( &display.surfaces, i );
		p_sr = (SurfaceRecord*)
		LinkedList_Get( &display.surfaces );
		if( p_sr->surface != surface ) {
			continue;
		}
		Widget_InvalidateArea( p_sr->widget, rect, SV_GRAPH_BOX );
		continue;
	}
}
Beispiel #14
0
/**
 * 获取部件中的无效区域
 * @param[in] widget	目标部件
 * @area[out] area	无效区域
 */
int Widget_GetInvalidArea( LCUI_Widget widget, LCUI_Rect *area )
{
	LCUI_Rect *p_rect;
	if( LinkedList_GetTotal(&widget->dirty_rects) <= 0 ) {
		return -1;
	}
	LinkedList_Goto( &widget->dirty_rects, 0 );
	DEBUG_MSG("list: %p, used node num: %d, current: %p, pos: %d\n",
		&widget->dirty_rects, widget->dirty_rects.used_node_num,
		widget->dirty_rects.current_node, widget->dirty_rects.current_node_pos);
	p_rect = (LCUI_Rect*)LinkedList_Get( &widget->dirty_rects );
	if( !p_rect ) {
		return -2;
	}
	DEBUG_MSG("p_rect: %d,%d,%d,%d\n", p_rect->x, p_rect->y, p_rect->w, p_rect->h);
	*area = *p_rect;
	return 0;
}
Beispiel #15
0
/** 解除 widget 与 sruface 的绑定 */
static void LCUIDisplay_UnbindSurface( LCUI_Widget widget )
{
	int i, n;
	SurfaceRecord *p_sr;

	n = LinkedList_GetTotal( &display.surfaces );
	for( i=0; i<n; ++i ) {
		LinkedList_Goto( &display.surfaces, i );
		p_sr = (SurfaceRecord*)
		LinkedList_Get( &display.surfaces );
		if( p_sr->widget != widget ) {
			continue;
		}
		Surface_Delete( p_sr->surface  );
		LinkedList_Delete( &display.surfaces );
		break;
	}
}
Beispiel #16
0
/** 将指定标签的样式数据从队列中删除,只删除队列尾部第一个匹配的标签 */
static void StyleTagStack_Delete( LCUI_StyleTagStack *tags, LCUI_StyleTagID tag )
{
	int i, total;
	LCUI_StyleTagData *p; 
	 
	total = LinkedList_GetTotal( tags );
	DEBUG_MSG("delete start, total tag: %d\n", total);
	if(total <= 0) {
		return;
	}
	for(i=total-1; i>=0; --i) {
		LinkedList_Goto( tags, i );
		p = (LCUI_StyleTagData*)LinkedList_Get( tags );
		if( p->tag_id == tag ) {
			LinkedList_Delete( tags );
			break;
		}
	} 
	DEBUG_MSG("delete end, total tag: %d\n", LinkedList_GetTotal( tags ));
}
Beispiel #17
0
/** 更新数据 */
void TextLayer_Update( LCUI_TextLayer* layer, LinkedList *rect_list )
{
	if( layer->task.update_bitmap ) {
		TextLayer_InvalidateAllRowRect( layer );
		TextLayer_ReloadCharBitmap( layer );
		TextLayer_InvalidateAllRowRect( layer );
		layer->task.update_bitmap = FALSE;
		layer->task.redraw_all = TRUE;
	}

	if( layer->task.update_typeset ) {
		TextLayer_TextTypeset( layer, layer->task.typeset_start_row );
		layer->task.update_typeset = FALSE;
		layer->task.typeset_start_row = 0;
	}

	/* 如果坐标偏移量有变化,记录各个文本行区域 */
	if( layer->new_offset_x != layer->offset_x
	 || layer->new_offset_y != layer->offset_y ) {
		TextLayer_InvalidateAllRowRect( layer );
		layer->offset_x = layer->new_offset_x;
		layer->offset_y = layer->new_offset_y;
		TextLayer_InvalidateAllRowRect( layer );
		layer->task.redraw_all = TRUE;
	}
	
	if( rect_list ) {
		int n;
		void *data_ptr;

		n = LinkedList_GetTotal( &layer->dirty_rect );
		LinkedList_Goto( &layer->dirty_rect, 0 );
		/* 转移脏矩形记录,供利用 */
		while(n--) {
			data_ptr = LinkedList_Get( &layer->dirty_rect );
			LinkedList_AddDataCopy( rect_list, data_ptr );
			LinkedList_ToNext( &layer->dirty_rect );
		}
	 } 
}
Beispiel #18
0
/** 清除已记录的无效矩形 */
void TextLayer_ClearInvalidRect( LCUI_TextLayer *layer )
{
	int n;
	LCUI_Rect *rect_ptr;
	LCUI_Graph invalid_graph;

	if( !layer->is_using_buffer ) {
		DirtyRectList_Destroy( &layer->dirty_rect );
		DirtyRectList_Init( &layer->dirty_rect );
		return;
	}

	n = LinkedList_GetTotal( &layer->dirty_rect );
	LinkedList_Goto( &layer->dirty_rect, 0 );
	while(n--) {
		rect_ptr = (LCUI_Rect*)LinkedList_Get( &layer->dirty_rect );
		Graph_Quote( &invalid_graph, &layer->graph, rect_ptr );
		Graph_FillAlpha( &invalid_graph, 0 );
		LinkedList_ToNext( &layer->dirty_rect );
	}
	DirtyRectList_Destroy( &layer->dirty_rect );
	DirtyRectList_Init( &layer->dirty_rect );
}
Beispiel #19
0
static int LCUIDisplay_Seamless( void )
{
	int i, n;
	LCUI_Widget widget;
	DEBUG_MSG("display.mode: %d\n", display.mode);
	switch( display.mode ) {
	case LDM_SEAMLESS:
		return 0;
	case LDM_FULLSCREEN:
	case LDM_WINDOWED:
	default:
		LCUIDisplay_CleanSurfaces();
		break;
	}
	n = LinkedList_GetTotal( &LCUIRootWidget->children );
	for( i=0; i<n; ++i ) {
		LinkedList_Goto( &LCUIRootWidget->children, i );
		widget = (LCUI_Widget)
		LinkedList_Get( &LCUIRootWidget->children );
		LCUIDisplay_BindSurface( widget );
	}
	display.mode = LDM_SEAMLESS;
	return 0;
}
Beispiel #20
0
/** 运行目标主循环 */
int LCUI_MainLoop_Run( LCUI_MainLoop loop )
{
	if( loop->state == STATE_RUNNING ) {
		_DEBUG_MSG("error: main-loop already running.");
		return -1;
	}
	DEBUG_MSG("loop: %p, enter\n", loop);
	loop->state = STATE_RUNNING;
	/* 将主循环记录插入至列表表头 */
	LinkedList_Goto( &MainApp.loop_list, 0 );
	LinkedList_Insert( &MainApp.loop_list, loop );
	MainApp.loop = loop;
	LCUIMutex_Lock( &MainApp.loop_changed );
	/* 广播,让其它线程交出主循环运行权 */
	LCUICond_Broadcast( &MainApp.loop_cond );
	/* 获取运行权 */
	LCUIMutex_Lock( &MainApp.loop_mutex );
	LCUIMutex_Unlock( &MainApp.loop_changed );
	loop->tid = LCUIThread_SelfID();
	while( loop->state != STATE_EXITED ) {
		if( LinkedList_GetTotal(&MainApp.task_list) <= 0 ) {
			DEBUG_MSG("loop: %p, sleeping...\n", loop);
			LCUICond_TimedWait( &MainApp.loop_cond, 1000 );
			DEBUG_MSG("loop: %p, wakeup\n", loop);
			/** 如果当前运行的主循环不是自己 */
			if( MainApp.loop != loop ) {
				loop->state = STATE_PAUSED;
				DEBUG_MSG("loop: %p, release control.\n", loop);
				LCUIMutex_Unlock( &MainApp.loop_mutex );
				/* 等待其它线程获得主循环运行权 */
				LCUIMutex_Lock( &MainApp.loop_changed );
				LCUIMutex_Unlock( &MainApp.loop_changed );
				DEBUG_MSG("loop: %p, waiting...\n", loop);
				/* 等待其它线程释放主循环运行权 */
				LCUIMutex_Lock( &MainApp.loop_mutex );
			}
			continue;
		}
		DEBUG_MSG("loop: %p, run task.\n", loop);
		LCUI_RunTask();
	}
	loop->state = STATE_EXITED;
	LinkedList_Goto( &MainApp.loop_list, 0 );
	LinkedList_Delete( &MainApp.loop_list );
	/* 获取处于列表表头的主循环 */
	loop = (LCUI_MainLoop)LinkedList_Get( &MainApp.loop_list );
	if( loop ) {
		/* 改变当前运行的主循环 */
		MainApp.loop = loop;
		LCUICond_Broadcast( &MainApp.loop_cond );
	}
	/* 释放运行权 */
	LCUIMutex_Unlock( &MainApp.loop_mutex );
	/* 如果列表为空,一般意味着LCUI需要退出了 */
	if( LinkedList_GetTotal( &MainApp.loop_list ) <= 0 ) {
		/** 广播,通知相关线程开始进行清理操作 */
		LCUICond_Broadcast( &MainApp.loop_list_empty );
	}
	DEBUG_MSG("loop: %p, exit\n", loop);
	return 0;
}
Beispiel #21
0
static int _Widget_ProcInvalidArea( LCUI_Widget w, LCUI_BOOL is_root, int x, int y,
			LCUI_Rect *valid_box, LCUI_DirtyRectList *rlist )
{
	int i, n, count;
	LCUI_Widget child;
	LCUI_Rect rect, child_box, *r;

	count = n = LinkedList_GetTotal( &w->dirty_rects );
	/* 取出当前记录的脏矩形 */
	for( i=0; i<n; ++i ) {
		LinkedList_Goto( &w->dirty_rects, 0 );
		r = (LCUI_Rect*)LinkedList_Get( &w->dirty_rects );
		/* 若有独立位图缓存,则重绘脏矩形区域 */
		if( Graph_IsValid(&w->graph) ) {
			LCUI_PaintContextRec_ paint;
			paint.rect = *r;
			Graph_Quote( &paint.canvas, &w->graph, &paint.rect );
			Widget_OnPaint( w, &paint );
		}
		/* 转换为相对于父部件的坐标 */
		rect.x = r->x;
		rect.y = r->y;
		/* 如果当前是根部件,则不用加上自身坐标 */
		if( !is_root ) {
			rect.x += w->base.box.graph.x;
			rect.y += w->base.box.graph.y;
		}
		rect.w = r->w;
		rect.h = r->h;
		/* 取出与容器内有效区域相交的区域 */
		if( LCUIRect_GetOverlayRect(&rect, valid_box, &rect) ) {
			/* 转换相对于根级部件的坐标 */
			rect.x += x;
			rect.y += y;
			DirtyRectList_Add( rlist, &rect );
		}
		LinkedList_Delete( &w->dirty_rects );
	}
	/* 若子级部件没有脏矩形记录 */
	if( !w->has_dirty_child ) {
		return count;
	}
	/* 缩小有效区域到当前部件内容框内,若没有重叠区域,则不向子级部件递归 */
	if( !LCUIRect_GetOverlayRect(valid_box, &w->base.box.content, &child_box) ) {
		return count;
	}
	/* 转换有效区域的坐标,相对于当前部件的内容框 */
	child_box.x -= w->base.box.content.x;
	child_box.y -= w->base.box.content.y;
	n = LinkedList_GetTotal( &w->children );
	/* 向子级部件递归 */
	for( i=0; i<n; ++i ) {
		child = (LCUI_Widget)LinkedList_Get( &w->children );
		if( !child->style.visible ) {
			continue;
		}
		count += _Widget_ProcInvalidArea(
			child, FALSE, child->base.box.graph.x + x,
			child->base.box.graph.y + y, &child_box, rlist
		);
	}
	return count;
}