My compound widget ignores PtSendEventToWidget()

Hi folks,

A question for you custom widget experts…

I am automating button activation of my UI for test automation, but am
having an issue with my custom widget not responding. Normal buttons
respond to the PtSendEventToWidget() calls just fine. The custom button
widget operates normally/fine on the touch screen. The issue is with
using PtSendEventToWidget() to activate it for automation.

My custom widget behaves as a button. It has additional labels that are
overlaid to reflect various information/status.

I am wondering if there is a resource or something I should set? I
tried setting some raw callbacks in the resources structure when you
create your widget class. This worked, but the touch screen
interraction stopped behaving nicely (dragging finger would activate
while pressed, or various other weird combinations). The raw callbacks
were set to Ph_EV_BUT_PRESS and _RELEASE. Again, this did not work
well, as it messed up the normal behavior. I just need to know how to
get an event through to the button component of my widget.

My custom widget’s structure looks like this:

typedef struct
{
PtCompoundWidget_t compound;
PtWidget_t *button; // heart of widget

PtWidget_t *components[ IB_NUM_WIDGET_TYPES ]; // various overlay labels
PtCallbackList_t *activate; // callback
} InteractiveButtonWidget_t;

typedef union
{
PtWidget_t core;
PtBasicWidget_t basic;
PtContainerWidget_t container;
PtCompoundWidget_t compound;
InteractiveButtonWidget_t ibutton;
} InteractiveButtonUnion_t;

The ‘button’ element is set to make a call to the function identified by
‘activate’. The callback function specified in the app builder is
stored in ‘activate’.

I am sending the following sequence to any button:

struct{
PhEvent_t event;
PhRect_t rect;
PhPointerEvent_t pevent;
} new_event;

memset( &new_event.rect, -1 , sizeof( new_event.rect ) );

new_event.event.processing_flags = 0;
new_event.event.type = Ph_EV_BUT_PRESS;
new_event.pevent.click_count = 1;
new_event.pevent.buttons = Ph_BUTTON_SELECT;
new_event.event.num_rects = 1;
PtSendEventToWidget( button, (PhEvent_t *) &new_event);


PtSendEventToWidget( button, (PhEvent_t *) &new_event );

memset( &new_event.rect, -1 , sizeof( new_event.rect ) );

new_event.event.type = Ph_EV_BUT_RELEASE;
new_event.event.subtype = Ph_EV_RELEASE_REAL;
new_event.pevent.click_count = 1;
new_event.pevent.buttons = Ph_BUTTON_SELECT;
new_event.event.num_rects = 1;

PtSendEventToWidget( button, (PhEvent_t *) &new_event );

This is QNX4, and I’ve looked through all the documentation and the
/qnx4/phtk example widgets, but did not see anything that seemed
applicable there.

Thank you (please modify my email address to reply – or reply to the
group),
Barry

Barry Robertson wrote:

I am sending the following sequence to any button:

struct{
PhEvent_t event;
PhRect_t rect;
PhPointerEvent_t pevent;
} new_event;

Could it be as simple as the fact that you’re not initializing most
parts of new_event to anything sensible? Have you tried adding a
“memset( &new_event, 0, sizeof(new_event) )” call here?

memset( &new_event.rect, -1 , sizeof( new_event.rect ) );

Why -1,-1 – isn’t that outside of your button?

new_event.event.processing_flags = 0;

It probably doesn’t matter here, but I think we recommend setting the
Pt_FAKE_EVENT flag in fake events…

new_event.event.type = Ph_EV_BUT_PRESS;
new_event.pevent.click_count = 1;
new_event.pevent.buttons = Ph_BUTTON_SELECT;
new_event.event.num_rects = 1;
PtSendEventToWidget( button, (PhEvent_t *) &new_event);

You’re sending it twice?

PtSendEventToWidget( button, (PhEvent_t *) &new_event );

memset( &new_event.rect, -1 , sizeof( new_event.rect ) );

Resetting processing_flags might be a good idea here. There’s a good
chance that something has set the CONSUMED flag or some other flags that
you might not want in there.

new_event.event.type = Ph_EV_BUT_RELEASE;
new_event.event.subtype = Ph_EV_RELEASE_REAL;
new_event.pevent.click_count = 1;
new_event.pevent.buttons = Ph_BUTTON_SELECT;
new_event.event.num_rects = 1;

PtSendEventToWidget( button, (PhEvent_t *) &new_event );

This is QNX4, and I’ve looked through all the documentation and the
/qnx4/phtk example widgets, but did not see anything that seemed
applicable there.

I’m simplifying an earlier question in the hopes of getting more to the
core of the question.

The goal is to use PtSendEventToWidget() to send button events to
buttons for automation. This works with normal PtButtons just fine. My
custom widget setup is supect, as those do not seem to “see” the same
events the other buttons do. They all work equally well in normal
touch-screen operation.

So, if you had a custom widget with, let’s strip it down, just a
PtButton (uses images) and a PtLabel (for a value) overlaid on top, how
would you set it up to get the same events as normal widgets (so that
PtSendEventToWidget) will cause the button to activate?

The various snippets of example code in the help documentation aren’t
helping.

Would it look like this?

// Current (actual) value for the button.
#define MY_ARG_CURRENT_VALUE Pt_RESOURCE( Pt_USER( 0 ), 1 )

// Function to call when the button is pressed.
#define MY_CB_ACTIVATE Pt_RESOURCE( Pt_USER( 0 ), 2 )


typedef struct
{
// This is the new widget’s superclass
PtCompoundWidget_t compound;

// The base object type
PtWidget_t *button;


// Component(s) to be overlaid on the button.
PtWidget_t *value;
int actualValue; // Set with MY_ARG_CURRENT_VALUE in PhAB

// Function to call when the user presses the button.
PtCallbackList_t *activate; // Set with MY_CB_ACTIVATE in PhAB

} MyButtonWidget_t;

typedef union
{
PtWidget_t core;
PtBasicWidget_t basic;
PtContainerWidget_t container;
PtCompoundWidget_t compound;
MyButtonWidget_t ibutton;
} MyButtonUnion_t;

// Widget Class Pointer
extern PtWidgetClassRef_t *MyButton;

Then the create function as follows:

PtWidgetClass_t *CreateMyButtonClass( void )
{
static const PtResourceRec_t resources[] =
{
{ MY_ARG_CURRENT_VALUE, MY_SetResource, MY_GetResource,
Pt_ARG_IS_STRING( PtLabelWidget_t, string ), 0 },
{ MY_CB_ACTIVATE, Pt_CHANGE_INVISIBLE, 0,
Pt_ARG_IS_CALLBACK( MyButtonWidget_t, activate ), 0 },
};

static PtArg_t args[] =
{
{ Pt_SET_VERSION, 110 },
{ Pt_SET_STATE_LEN, sizeof( MyButtonWidget_t ) },
{ Pt_SET_DFLTS_F, ( long )MyButtonDefaults },
{ Pt_SET_FLAGS, Pt_TRUE, Pt_COMPOUND },
{ Pt_SET_NUM_RESOURCES, sizeof( resources ) / sizeof( resources[ 0
] ) },
{ Pt_SET_RESOURCES, ( long )resources, sizeof( resources ) /
sizeof( resources[ 0 ] ) },
{ Pt_SET_NUM_BLOCKED_RESOURCES, 0 },
{ Pt_SET_REALIZED_F, ( long )MyButtonRealized },
{ Pt_ARG_FILL_COLOR, Pg_TRANSPARENT, 0 }
};

// Create the widget class…
MyButton->wclass = PtCreateWidgetClass( PtCompound, 0, sizeof( args )
/ sizeof( args[ 0 ] ), args );

return( MyButton->wclass );
}


I probably mangled that a bit. Renamed some things and removed some
extra parts of the new widget. Again, I just need PtSendEventToWidget()
to actually cause the button part of this thing to activate. I wonder
if there is something in the creation resources that I need.

Maybe I’ll just avoid this altogether and rewrite as a C++ class.

Thanks,
Barry