Prima

 view release on metacpan or  search on metacpan

unix/menu.c  view on Meta::CPAN

	} else if ( XT_IS_ICON(X(src))) {
		/* argb icon over non-argb surface */
		IconHandle split;
		if ( !dispose_src ) {
			i = (PIcon)(src = i->self->dup(src));
			dispose_src = true;
		}
		if ( i->maskType == 8 ) {
			i->self->set_type(src, imRGB);
			i->self->premultiply_alpha(src, NULL);
			i->self->set_maskType(src, 1);
		}
		split = i->self->split(src);
		dst->use_stippling = disabled;
		dst->xor = CImage(split.xorMask)->bitmap(split.xorMask);
		dst->and = CImage(split.andMask)->bitmap(split.andMask);
		Object_destroy( split.xorMask );
		Object_destroy( split.andMask );
	} else {
		dst-> use_stippling = disabled;
	FALLBACK:
		if ( guts.dynamicColors ) {
			Handle dup = i-> self-> dup(src);
			if ( dispose_src ) Object_destroy(src);
			dispose_src = true;
			convert_to_lowres(dup);
			i = (PIcon) (src = dup);
		}
		dst->xor = i->self->bitmap(src);
	}

	if ( dispose_src )
		Object_destroy( src );
	if ( dst->xor ) {
		prima_refcnt_inc(dst->xor);
		protect_object(dst->xor);
	}
	if ( dst->and ) {
		prima_refcnt_inc(dst->and);
		protect_object(dst->and);
	}

	return true;
#undef USE_ARGB_SHADING
}

static void
update_menu_window( PMenuSysData XX, PMenuWindow w)
{
	int x, y = 2 + 2, startx, icon_width;
	Bool vertical = w != &XX-> wstatic, layered;
	PMenuItemReg m = w->m;
	PUnixMenuItem ix;
	int lastIncOk = 1;
	PCachedFont kf = XX-> font;
	uint32_t *xft_map8 = NULL;
	PWindow owner = ( PWindow)(PComponent( w-> self)-> owner);

#ifdef USE_XFT
	{
		const char * encoding = ( XX-> type. popup) ?
			owner-> popupFont. encoding :
			owner-> menuFont. encoding;
		xft_map8 = prima_xft_map8( encoding);
	}
#endif
	layered = vertical ? false : X(owner)->flags. layered;

	free_unix_items( w);
	w-> num = item_count( w);
	ix = w-> um = malloc( sizeof( UnixMenuItem) * w-> num);
	if ( !ix) return;
	bzero( w-> um, sizeof( UnixMenuItem) * w-> num);

	m = w->m;
	if ( vertical ) {
		icon_width = MENU_CHECK_XOFFSET;
		while (m) {
			if ( m-> icon && PObject( m-> icon)-> stage < csDead) {
				PImage i = ( PImage) m-> icon;
				if ( i-> w > icon_width ) icon_width = i-> w;
			}
			m = m-> next;
		}
		startx = x = MENU_XOFFSET * 4 + MENU_CHECK_XOFFSET + icon_width;
	} else {
		startx = x = icon_width = 0;
	}

	if ( vertical) w-> last = -1;
	w-> selected = -100;
	m = w->m;
	while ( m) {
		ix-> icon_width = icon_width;

		if ( m-> flags. custom_draw ) {
			Event ev = { cmMenuItemMeasure };
			ev.gen.P.x = 0;
			ev.gen.P.y = 0;
			ev.gen.i = m-> id;
			CComponent(w-> self)-> message(w-> self,&ev);
			ix-> width  = ev.gen.P.x;
			ix-> height = ev.gen.P.y + MENU_ITEM_GAP * 2;
		} else if ( m-> flags. divider) {
			ix-> height = vertical ? MENU_ITEM_GAP * 2 : 0;
		} else {
			int l = 0, w, h;
			if ( m-> text) {
				int i, ntildas = 0;
				char * t = m-> text;
				ix-> height = MENU_ITEM_GAP * 2 + kf-> font. height;
				for ( i = 0; t[i]; i++) {
					if ( t[i] == '~' && t[i+1]) {
						ntildas++;
						if ( t[i+1] == '~')
							i++;
					}
				}
				ix-> width += startx + get_text_width( kf, m-> text, i,
					m-> flags. utf8_text, xft_map8);
				if ( ntildas)
					ix-> width -= ntildas * get_text_width( kf, "~", 1, false, xft_map8);

unix/menu.c  view on Meta::CPAN

	return true;
}

#undef DECL_DRAW

static void
handle_menu_expose( XEvent *ev, XWindow win, Handle self)
{
	DEFMM;
	PMenuWindow w;
	PUnixMenuItem ix;
	PMenuItemReg m;
	Bool vertical;
	int sz = 1024, x, y;
	char *s;
	int right, last = 0;
	int descent;
	PCachedFont kf;
	MenuDrawRec draw;
	unsigned long clr = 0;
	Color rgb = 0;
	PWindow owner;
	Bool selected = false;
	XRectangle r;
	Region rgn;

	kf = XX-> font;
	XX-> paint_pending = false;
	if ( XX-> wstatic. w == win) {
		w = XX-> w;
		vertical = false;
	} else {
		if ( !( w = get_menu_window( self, win))) return;
		vertical = true;
	}
	ix = w-> um;
	right  = vertical ? 0 : w-> right;
	m  = w-> m;
	if ( !ix) return;

	owner = ( PWindow)(PComponent( w-> self)-> owner);
	bzero( &draw, sizeof( draw));
	draw. win = win;
	draw. layered = vertical ? false : X(owner)->flags. layered;
	if ( draw.layered ) {
		XGCValues gcv;
		gcv. graphics_exposures = false;
		gcv. cap_style          = CapProjecting;
		gcv. line_width         = 1;
		draw. gc = XCreateGC( DISP, X(owner)->gdrawable,
			GCGraphicsExposures | GCCapStyle | GCLineWidth,
			&gcv
		);
		draw. c  = XX->argb_c;
	} else {
		draw. gc = guts. menugc;
		draw. c  = XX->c;
	}
#ifdef USE_XFT
	if ( kf-> xft) {
		char * encoding = ( XX-> type. popup) ?
			owner-> popupFont. encoding :
			owner-> menuFont. encoding;
		draw. xft_map8 = prima_xft_map8( encoding);
		draw. xft_drawable = XftDrawCreate( DISP, win,
			draw.layered ? guts. argb_visual. visual : guts. visual. visual,
			draw.layered ? guts. argbColormap : guts. defaultColormap);
		descent = kf-> xft-> descent;
	} else
#endif
	descent = kf-> fs->max_bounds.descent;

	r. x = ev-> xexpose. x;
	r. y = ev-> xexpose. y;
	r. width = ev-> xexpose. width;
	r. height = ev-> xexpose. height;
	rgn = XCreateRegion();
	XUnionRectWithRegion( &r, rgn, rgn);
	XSetRegion( DISP, draw.gc, rgn);
#ifdef USE_XFT
	if ( draw. xft_drawable) XftDrawSetClip(( XftDraw*) draw.xft_drawable, rgn);
#endif
	XCHECKPOINT;
	CLIP_ARGB_PICTURE(w->argb_picture, rgn);

#ifdef USE_XFT
	if ( !kf-> xft)
#endif
		XSetFont( DISP, draw.gc, kf-> id);

	y = vertical ? 2 : 0;
	x = 0;
	if ( !( s = malloc( sz))) goto EXIT;
	DRAW(background);
	while ( m) {
		int deltaY = ix-> height;

		/* printf("%d %d %d %s\n", last, w-> selected, w-> last, m-> text); */
		selected = last == w-> selected;
		if ( selected ) {
			if ( !m-> flags. custom_draw ) {
				Point sz = menu_item_size( XX, w, last);
				Point p = menu_item_offset( XX, w, last);
				XSetForeground( DISP, draw.gc, draw.c[ciHilite]);
				XFillRectangle( DISP, win, draw.gc, p.x, p.y, sz. x, sz.y);
			}
			clr = draw.c[ciHiliteText];
			rgb = XX-> rgb[ciHiliteText];
		} else {
			clr = draw.c[ciFore];
			rgb = XX-> rgb[ciFore];
		}

		if ( last > w-> last) {
			DRAW(guillemots);
			break;
		}

		if ( m-> flags. disabled) {
			clr = draw.c[ciDisabledText];
			rgb = XX-> rgb[ ciDisabledText];
		}

unix/menu.c  view on Meta::CPAN

	int px;
	if ( guts. currentMenu != self) return;

	w = get_menu_window( self, win);
	px = menu_point2item( XX, w, ev-> xmotion.x, ev-> xmotion.y, NULL);
	menu_select_item( XX, w, px);
	m = w-> m;
	if ( px >= 0) {
		int x = px;
		while ( x--) m = m-> next;
		if ( px != w-> last + 1) m = m-> down;
		if ( !w-> next || w-> next-> m != m) {
			apc_timer_set_timeout( MENU_TIMER, (XX-> wstatic. w == win) ? 2 : guts. menu_timeout);
			XX-> focused = w;
		}
	}
	while ( w-> next) {
		menu_select_item( XX, w-> next, -1);
		w = w-> next;
	}
}

static void
handle_menu_button( XEvent *ev, XWindow win, Handle self)
{
	DEFMM;
	int px, first = 0;
	PMenuWindow w;
	XWindow focus = NULL_HANDLE;
	if ( prima_no_input( X(PComponent(self)->owner), false, true)) return;
	if ( ev-> xbutton. button != Button1) return;

	if ( XX-> wstatic. w == win) {
		Handle x = guts. focused, owner = PComponent(self)-> owner;
		while ( x && !X(x)-> type. window) x = PComponent( x)-> owner;
		if ( x != owner) {
			XSetInputFocus( DISP, focus = PComponent( owner)-> handle,
				RevertToNone, ev-> xbutton. time);
		}
	}

	if ( !( w = get_menu_window( self, win))) {
		prima_end_menu();
		return;
	}
	px = menu_point2item( XX, w, ev-> xbutton. x, ev-> xbutton.y, NULL);
	if ( px < 0) {
		if ( XX-> wstatic. w == win)
			prima_end_menu();
		return;
	}
	if ( guts. currentMenu != self) {
		int rev;
		if ( ev-> type == ButtonRelease) return;
		if ( guts. currentMenu)
			prima_end_menu();
		if ( focus)
			XX-> focus = focus;
		else
			XGetInputFocus( DISP, &XX-> focus, &rev);
		if ( !XX-> type. popup) {
			Handle topl = PComponent( self)-> owner;
			Handle who  = ( Handle) hash_fetch( guts.windows, (void*)&XX-> focus, sizeof(XX-> focus));
			while ( who) {
				if ( XT_IS_WINDOW(X(who))) {
					if ( who != topl) XX-> focus = PComponent( topl)-> handle;
					break;
				}
				who = PComponent( who)-> owner;
			}
		}
		first = 1;
	}
	XSetInputFocus( DISP, XX-> w-> w, RevertToNone, CurrentTime);
	guts. currentMenu = self;
	if ( first && ( ev-> type == ButtonPress) && ( !send_cmMenu( self, NULL)))
		return;
	if ( !first && ( ev-> type == ButtonPress)) return;
	apc_timer_stop( MENU_TIMER);
	menu_select_item( XX, w, px);
	if ( !ev-> xbutton. send_event) {
		if ( !menu_enter_item( XX, w, px, ( ev-> type == ButtonPress) ? 0 : 1))
			return;
	} else
		XX-> focused = w;

	ev-> xbutton. x += w-> pos. x;
	ev-> xbutton. y += w-> pos. y;
	if ( w-> next &&
		ev-> xbutton. x >= w-> next-> pos.x &&
		ev-> xbutton. y >= w-> next-> pos.y &&
		ev-> xbutton. x <  w-> next-> pos.x + w-> next-> sz.x &&
		ev-> xbutton. y <  w-> next-> pos.y + w-> next-> sz.y
	) {
		/* simulate mouse move, as X are stupid enough to not do it  */
		int x = ev-> xbutton.x, y = ev-> xbutton. y;
		ev-> xmotion. x = x - w-> next-> pos. x;
		ev-> xmotion. y = y - w-> next-> pos. y;
		win = w-> next-> w;
		handle_menu_motion(ev, win, self);
	}
}

static void
handle_menu_focus_out( XEvent *ev, XWindow win, Handle self)
{
	if ( self != guts. currentMenu) return;

	switch ( ev-> xfocus. detail) {
	case NotifyVirtual:
	case NotifyPointer:
	case NotifyPointerRoot:
	case NotifyDetailNone:
	case NotifyNonlinearVirtual:
		return;
	}
	apc_timer_stop( MENU_UNFOCUS_TIMER);
	apc_timer_start( MENU_UNFOCUS_TIMER);
	guts. unfocusedMenu = self;
}

static void
handle_menu_focus_in( XEvent *ev, XWindow win, Handle self)
{
	if ( guts. unfocusedMenu && self == guts. unfocusedMenu && self == guts. currentMenu) {
		switch ( ev-> xfocus. detail) {
		case NotifyVirtual:
		case NotifyPointer:
		case NotifyPointerRoot:
		case NotifyDetailNone:
		case NotifyNonlinearVirtual:
			return;
		}
		apc_timer_stop( MENU_UNFOCUS_TIMER);
		guts. unfocusedMenu = NULL_HANDLE;
	}
}

static void
handle_menu_key( XEvent *ev, XWindow win, Handle self)
{
	DEFMM;
	char str_buf[ 256];
	KeySym keysym;
	int str_len, d = 0, piles = 0;
	PMenuWindow w;
	PMenuItemReg m;
	int keycode, code, mod, key;

	str_len = XLookupString( &ev-> xkey, str_buf, 256, &keysym, NULL);
	if ( prima_handle_menu_shortcuts( PComponent(self)-> owner, ev, keysym) != 0)
		return;

	if ( self != guts. currentMenu) return;
	apc_timer_stop( MENU_TIMER);
	if ( !XX-> focused) return;
	/* navigation */
	w = XX-> focused;
	m = w-> m;
	switch (keysym) {
	case XK_Left:
	case XK_KP_Left:
		if ( w == &XX-> wstatic) { /* horizontal menu */
			d--;
		} else if ( w != XX-> w) { /* not a popup root */
			if ( w-> prev) menu_window_delete_downlinks( XX, w-> prev);
			if ( w-> prev == &XX-> wstatic) {
				d--;
				piles = 1;
			} else
				return;
		}
		break;
	case XK_Right:
	case XK_KP_Right:
		if ( w == &XX-> wstatic) { /* horizontal menu */
			d++;
		} else if ( w-> selected >= 0) {
			int sel;
			sel = w-> selected;
			if ( sel >= 0) {
				while ( sel--) m = m-> next;
			}
			if ( m-> down || w-> selected == w-> last + 1) {
				if ( menu_enter_item( XX, w, w-> selected, 1) && w-> next)
					menu_select_item( XX, w-> next, 0);
			} else if ( w-> prev == &XX-> wstatic) {
				menu_window_delete_downlinks( XX, XX-> w);
				piles = 1;
				d++;
			} else
				return;
		}
		break;
	case XK_Up:
	case XK_KP_Up:
		if ( w != &XX-> wstatic) d--;
		break;
	case XK_Down:
	case XK_KP_Down:
		if ( w == &XX-> wstatic) {
			int sel = w-> selected;
			if ( sel >= 0) {
				while ( sel--) m = m-> next;
			}
			if ( m-> down || w-> selected == w-> last + 1) {
				if ( menu_enter_item( XX, w, w-> selected, 1) && w-> next)
					menu_select_item( XX, w-> next, 0);
			}
		} else
			d++;
		break;
	case XK_KP_Enter:
	case XK_Return:
		menu_enter_item( XX, w, w-> selected, 1);
		return;
	case XK_Escape:
		if ( w-> prev)
			menu_window_delete_downlinks( XX, w-> prev);
		else
			prima_end_menu();
		return;
	default:
		goto NEXT_STAGE;
	}

unix/menu.c  view on Meta::CPAN

	for ( i = 0; i <= ciMaxId; i++)
		XX-> c[i] = prima_allocate_color(
			NULL_HANDLE,
			prima_map_color( PWindow(owner)-> menuColor[i], NULL),
			NULL);
	XX-> layered = X(owner)->flags. layered;
	if ( XX-> layered ) {
		for ( i = 0; i <= ciMaxId; i++)
			XX-> argb_c[i] = argb_color(
				prima_map_color( PWindow(owner)-> menuColor[i], NULL)
			);
	}
	apc_menu_set_font( self, &PWindow(owner)-> menuFont);
	return true;
}

Bool
apc_menu_destroy( Handle self)
{
	if ( guts. currentMenu == self) prima_end_menu();
	return true;
}

PFont
apc_menu_default_font( PFont f)
{
	memcpy( f, &guts. default_menu_font, sizeof( Font));
	return f;
}

Color
apc_menu_get_color( Handle self, int index)
{
	Color c;
	if ( index < 0 || index > ciMaxId) return clInvalid;
	c = M(self)-> c[index];
	if ( guts. palSize > 0)
		return guts. palette[c]. composite;
	return
		((((c & guts. visual. blue_mask)  >> guts. screen_bits. blue_shift) << 8) >> guts. screen_bits. blue_range) |
	(((((c & guts. visual. green_mask) >> guts. screen_bits. green_shift) << 8) >> guts. screen_bits. green_range) << 8) |
	(((((c & guts. visual. red_mask)   >> guts. screen_bits. red_shift)   << 8) >> guts. screen_bits. red_range) << 16);
}

PFont
apc_menu_get_font( Handle self, PFont font)
{
	DEFMM;
	if ( !XX-> font)
		return apc_menu_default_font( font);
	memcpy( font, &XX-> font-> font, sizeof( Font));
	return font;
}

Bool
apc_menu_set_color( Handle self, Color color, int i)
{
	DEFMM;
	if ( i < 0 || i > ciMaxId) return false;
	XX-> rgb[i] = prima_map_color( color, NULL);
	if ( !XX-> type.popup) {
		if ( X(PWidget(self)-> owner)-> menuColorImmunity) {
			X(PWidget(self)-> owner)-> menuColorImmunity--;
			return true;
		}
		if ( X_WINDOW) {
			prima_palette_replace( PWidget(self)-> owner, false);
			if ( !XX-> paint_pending) {
				XClearArea( DISP, X_WINDOW, 0, 0, XX-> w-> sz.x, XX-> w-> sz.y, true);
				XX-> paint_pending = true;
			}
		}
	} else {
		XX-> c[i] = prima_allocate_color( NULL_HANDLE, XX-> rgb[i], NULL);
		if ( XX-> layered )
			XX-> argb_c[i] = argb_color( prima_map_color( XX->rgb[i], NULL));
	}
	return true;
}

/* apc_menu_set_font is in apc_font.c */

void
menu_touch( Handle self, PMenuItemReg who, Bool kill)
{
	DEFMM;
	PMenuWindow w, lw = NULL;

	if ( guts. currentMenu != self) return;

	w = XX-> w;
	while ( w) {
		if ( w-> m == who) {
			if ( kill || lw == NULL)
				prima_end_menu();
			else
				menu_window_delete_downlinks( M(self), lw);
			return;
		}
		lw = w;
		w = w-> next;
	}
}

static void
menu_reconfigure( Handle self)
{
	XEvent ev;
	DEFMM;
	ev. type = ConfigureNotify;
	ev. xconfigure. width  = X(PComponent(self)-> owner)-> size.x;
	ev. xconfigure. height = X(PComponent(self)-> owner)-> size.y;
	XX-> w-> sz. x = ev. xconfigure. width - 1; /* force cache flush */
	prima_handle_menu_event( &ev, PMenu(self)-> handle, self);
}

static void
menubar_repaint( Handle self)
{
	DEFMM;
	if ( !XT_IS_POPUP(XX) && XX-> w == &XX-> wstatic && PMenu(self)-> handle) {

unix/menu.c  view on Meta::CPAN

	return true;
}

Bool
apc_menu_item_set_check( Handle self, PMenuItemReg m)
{
	menu_touch( self, m, false);
	return true;
}

Bool
apc_menu_item_set_enabled( Handle self, PMenuItemReg m)
{
	menu_touch( self, m, false);
	menu_update_item(self, m);
	menubar_repaint( self);
	return true;
}

Bool
apc_menu_item_set_icon( Handle self, PMenuItemReg m)
{
	menu_touch( self, m, false);
	menu_update_item(self, m);
	menubar_repaint( self);
	return true;
}


Bool
apc_menu_item_set_image( Handle self, PMenuItemReg m)
{
	menu_touch( self, m, false);
	menu_update_item(self, m);
	menubar_repaint( self);
	return true;
}

Bool
apc_menu_item_set_key( Handle self, PMenuItemReg m)
{
	menu_touch( self, m, false);
	return true;
}

Bool
apc_menu_item_set_text( Handle self, PMenuItemReg m)
{
	menu_touch( self, m, false);
	menubar_repaint( self);
	return true;
}

ApiHandle
apc_menu_get_handle( Handle self)
{
	return NULL_HANDLE;
}

Bool
apc_popup_create( Handle self, Handle owner)
{
	DEFMM;
	apc_menu_destroy( self);
	XX-> type.menu = true;
	XX-> type.popup = true;
	return true;
}

PFont
apc_popup_default_font( PFont f)
{
	memcpy( f, &guts. default_menu_font, sizeof( Font));
	return f;
}

Bool
apc_popup( Handle self, int x, int y, Rect *anchor)
{
	DEFMM;
	PMenuItemReg m;
	PMenuWindow w;
	XWindow dummy;
	PDrawableSysData owner;
	int dx, dy;

	prima_end_menu();
	if (!(m=TREE)) return false;
	guts. currentMenu = self;
	if ( !send_cmMenu( self, NULL)) return false;
	if (!(w = get_window(self,m))) return false;
	update_menu_window(XX, w);
	if ( anchor-> left == 0 && anchor-> right == 0 && anchor-> top == 0 && anchor-> bottom == 0) {
		anchor-> left = anchor-> right = x;
		anchor-> top = anchor-> bottom = y;
	} else {
		if ( x < anchor-> left)   anchor-> left   = x;
		if ( x > anchor-> right)  anchor-> right  = x;
		if ( y < anchor-> bottom) anchor-> bottom = y;
		if ( y > anchor-> top)    anchor-> top    = y;
	}
	owner = X(PComponent(self)->owner);
	y = owner-> size. y - y;
	anchor-> bottom = owner-> size. y - anchor-> bottom;
	anchor-> top = owner-> size. y - anchor-> top;
	dx = dy = 0;
	XTranslateCoordinates( DISP, owner->udrawable, guts. root, dx, dy, &dx, &dy, &dummy);
	x += dx;
	y += dy;
	anchor-> left   += dx;
	anchor-> right  += dx;
	anchor-> top    += dy;
	anchor-> bottom += dy;
	if ( anchor-> bottom + w-> sz.y <= guts. displaySize.y)
		y = anchor-> bottom;
	else if ( w-> sz. y < anchor-> top)
		y = anchor-> top - w-> sz. y;
	else
		y = 0;
	if ( anchor-> right + w-> sz.x <= guts. displaySize.x)
		x = anchor-> right;
	else if ( w-> sz.x < anchor-> left)
		x = anchor-> left - w-> sz. x;
	else
		x = 0;
	w-> pos. x = x;
	w-> pos. y = y;
	XX-> focused = w;
	XGetInputFocus( DISP, &XX-> focus, &dx);
	XMoveWindow( DISP, w->w, x, y);
	XMapRaised( DISP, w->w);
	XSetInputFocus( DISP, w->w, RevertToNone, CurrentTime);
	XFlush( DISP);
	XCHECKPOINT;
	return true;
}

Bool
apc_window_set_menu( Handle self, Handle menu)
{
	DEFXX;
	int y = XX-> menuHeight;
	Bool repal = false;

	if ( XX-> menuHeight > 0) {
		PMenu m = ( PMenu) PWindow( self)-> menu;
		PMenuWindow w = M(m)-> w;
		if ( m-> handle == guts. currentMenu) prima_end_menu();
		hash_delete( guts. menu_windows, &w-> w, sizeof( w-> w), false);
		DELETE_ARGB_PICTURE(w->argb_picture);
		XDestroyWindow( DISP, w-> w);
		free_unix_items( w);
		m-> handle = NULL_HANDLE;
		M(m)-> paint_pending = false;
		M(m)-> focused = NULL;
		y = 0;
		repal = true;
	}

	if ( menu) {
		PMenu m = ( PMenu) menu;
		XSetWindowAttributes attrs;
		unsigned long valuemask;
		attrs. event_mask =           KeyPressMask | ButtonPressMask  | ButtonReleaseMask
			| EnterWindowMask     | LeaveWindowMask | ButtonMotionMask | ExposureMask
			| StructureNotifyMask | FocusChangeMask | OwnerGrabButtonMask
			| PointerMotionMask;
		attrs. do_not_propagate_mask = attrs. event_mask;
		attrs. win_gravity = NorthWestGravity;
		valuemask = CWWinGravity| CWEventMask;
		if ( XF_LAYERED(XX)) {
			valuemask |= CWBackPixel | CWBorderPixel;
			attrs. background_pixel = 0xFFFFFFFF;
			attrs. border_pixel     = 0xFFFFFFFF;
		}
		y = PWindow(self)-> menuFont. height + MENU_ITEM_GAP * 2;
		M(m)-> w-> w = m-> handle = XCreateWindow( DISP, X_WINDOW,
			0, 0, 1, 1, 0, CopyFromParent,
			InputOutput, CopyFromParent, valuemask, &attrs);
		CREATE_ARGB_PICTURE(M(m)->w->w, X(self)->flags.layered ? 32 : 0, M(m)->w->argb_picture);
		hash_store( guts. menu_windows, &m-> handle, sizeof( m-> handle), m);
		XResizeWindow( DISP, m-> handle, XX-> size.x, y);
		XMapRaised( DISP, m-> handle);
		M(m)-> paint_pending = true;
		M(m)-> focused = NULL;
		update_menu_window(M(m), M(m)-> w);
		menu_reconfigure( menu);
		repal = true;
		/* make it immune to necessary color change calls */
		XX-> menuColorImmunity = ciMaxId + 1;
	}
	prima_window_reset_menu( self, y);
	if ( repal) prima_palette_replace( self, false);
	if ( menu) {
		int i;
		Bool layered = XF_LAYERED(XX);
		XX->flags.layered = false; /* we need non-layered colors for popup menus */
		for ( i = 0; i <= ciMaxId; i++) {
			M(menu)-> c[i] = prima_allocate_color( self,
				prima_map_color( PWindow(self)-> menuColor[i], NULL), NULL);
		}
		i = MENU_PALETTE_SIZE - 1;
		M(menu)-> c[i] = prima_allocate_color( self, 0x404040, NULL);
		XX->flags.layered = layered;
		M(menu)-> layered = XX->flags. layered;
		if ( M(menu)-> layered ) {
			for ( i = 0; i <= ciMaxId; i++) 
				M(menu)-> argb_c[i] = argb_color(
					prima_map_color( PWindow(self)-> menuColor[i], NULL)
				);
			i = MENU_PALETTE_SIZE - 1;
			M(menu)-> argb_c[i] = prima_allocate_color( self, 0x404040, NULL);
		}
	}
	return true;
}

Bool
apc_menu_item_begin_paint( Handle self, PEvent event)
{
	PaintEvent * pe = (PaintEvent*) event-> gen.p;
	PDrawableSysData YY = X(event->gen.H);

	YY-> type.drawable = 1;
	YY-> type.widget   = 1;
	YY-> flags.layered = pe->layered;
#ifdef HAVE_X11_EXTENSIONS_XRENDER_H
	YY-> argb_picture  = M(pe->self)->w->argb_picture;
#endif
	YY-> gdrawable     = pe->win;
	YY-> size          = event-> gen.P;
	YY-> visual        = pe->layered ? &guts. argb_visual : &guts. visual;
	YY-> colormap      = pe->layered ? guts. argbColormap : guts. defaultColormap;
	prima_prepare_drawable_for_painting(event-> gen.H, false );
	YY-> flags.paint   = 1;
	XCHECKPOINT;

	return true;

}

Bool
apc_menu_item_end_paint( Handle self, PEvent event)
{
#ifdef HAVE_X11_EXTENSIONS_XRENDER_H
	PaintEvent * pe = (PaintEvent*) event-> gen.p;
	if ( &M(pe->self)->wstatic == M(self)-> w)
		X(event->gen.H)->argb_picture = 0;
#endif

	prima_cleanup_drawable_after_painting(event->gen.H);
	return true;
}



( run in 1.483 second using v1.01-cache-2.11-cpan-364913b4093 )