Skip navigation.
Home
The QNX Community Portal

View topic - filter keys

filter keys

Read-only archive of qnx.gui (Creating graphical applications within a GUI environment, such as Photon or PhAB) at inn.qnx.com

filter keys

Postby alain » Fri Jun 04, 2004 2:09 pm

I've created a region between ROOT and DEVICE to filter some keys but I
reemit the event I don't want to block, nobody receive it.

This how I create the region:

void CreateRcvRegion(void)
{
PhArea_t area;
PtArg_t arg[20];
short numargs = 0;
long fields;

fields = Ph_REGION_PARENT
| Ph_REGION_EV_SENSE
| Ph_REGION_IN_FRONT
| Ph_REGION_EV_OPAQUE
| Ph_REGION_FLAGS
| Ph_REGION_INPUT_GROUP;
PtSetArg( &arg[numargs++], Pt_ARG_REGION_FIELDS, fields, fields );


area.pos.x = area.pos.y = 0; area.size.w = area.size.h = SHRT_MAX;
PtSetArg( &arg[numargs++], Pt_ARG_AREA, &area, 0 );

PtSetArg( &arg[numargs++], Pt_ARG_REGION_PARENT, Ph_ROOT_RID, 0
);
PtSetArg( &arg[numargs++], Pt_ARG_REGION_SENSE, Ph_EV_KEY,
Ph_EV_KEY);
PtSetArg( &arg[numargs++], Pt_ARG_REGION_OPAQUE, Ph_EV_KEY,
Ph_EV_KEY);
PtSetArg( &arg[numargs++], Pt_ARG_REGION_INPUT_GROUP, 0, 0);
PtSetArg( &arg[numargs++], Pt_ARG_REGION_FLAGS, Ph_KBD_REGION,
Ph_KBD_REGION);
PtSetArg( &arg[numargs++], Pt_ARG_REGION_INFRONT, Ph_DEV_RID, 0
);
PtSetArg( &arg[numargs++], Pt_ARG_FILL_COLOR,
Pg_TRANSPARENT, 0 );

rcv_region_widget = PtCreateWidget( PtRegion, NULL, numargs, arg );
PtAddEventHandler( rcv_region_widget, Ph_EV_KEY, cbRegionFilterEvent,
NULL );
PtRealizeWidget( rcv_region_widget );

/*
* this is going to be a Raw event, not a key event, because
* we want to emit it rootwards towards the Device region,
* which will consume, focus, and reemit our event as a true
* key event
*/
phEvent.processing_flags = Ph_FAKE_EVENT;
phEvent.type = Ph_EV_KEY;
phEvent.subtype = Ph_EV_KEY;
phEvent.emitter.rid = PtWidgetRid( rcv_region_widget );
phEvent.collector.rid = Ph_ROOT_RID;
phEvent.input_group = PhInputGroup( NULL );
phEvent.data_len = sizeof( PhKeyEvent_t );
phEvent.num_rects = 1;

/*
* the event's rectangle covers the entire event space;
* this saves us from finding out the extent of the
* collector's region
*/
phEvent_rect.ul.x = phEvent_rect.ul.y = SHRT_MIN;
phEvent_rect.lr.x = phEvent_rect.lr.y = SHRT_MAX;

misc_verbose(verbose, 1, "rid %d\n", (int)phEvent.emitter.rid);
}


Here is how I filter ou the events:

int cbRegionFilterEvent( PtWidget_t *widget, void *data, PtCallbackInfo_t
*cbinfo )
{
PhKeyEvent_t * keyEvent = NULL;

if ( (cbinfo == NULL)
|| (cbinfo->event == NULL) )
return Pt_CONTINUE;

switch (cbinfo->event->type) {
case Ph_EV_KEY :

keyEvent = (PhKeyEvent_t*)PhGetData(cbinfo->event);
if (keyEvent == NULL)
return Pt_CONTINUE;

if (keyEvent->key_flags & Pk_KF_Key_Down) {
misc_verbose(verbose, 1, "Rcv Key Down\n");

misc_verbose(verbose, 2, " key_mods :
0x%08x\n", (unsigned)keyEvent->key_mods);

if (keyEvent->key_flags & Pk_KF_Sym_Valid) {
misc_verbose(verbose, 2, " key_sym :
0x%08x\n", (unsigned)keyEvent->key_sym);

switch ((unsigned)keyEvent->key_sym) {
case T5_KEY_STOP_L:
break;

case T5_KEY_START_L:
break;

case T5_KEY_SLOW_L:
break;

case T5_KEY_TEMP_L:
break;

case T5_KEY_STOP_R:
break;

case T5_KEY_START_R:
break;

case T5_KEY_SLOW_R:
break;

case T5_KEY_TEMP_R:
break;

case T5_KEY_STOP_DOF:
break;

case T5_KEY_START_DOF:
break;

default:
misc_verbose(verbose, 1, "reemit event\n");
PhEventEmit( &phEvent, &phEvent_rect,
&keyEvent );
break;
}
}
if (keyEvent->key_flags & Pk_KF_Cap_Valid)
misc_verbose(verbose, 2, " key_cap :
0x%08x\n", (unsigned)keyEvent->key_cap);
}
break;

default:
misc_verbose(verbose, 1, "reemit event\n");
PhEventEmit( &phEvent, &phEvent_rect, &keyEvent );
break;
}

return Pt_CONTINUE;
}


What is wrong ?

Thanks,
Alain.
alain
Active Member
 
Posts: 68
Joined: Tue Apr 27, 2004 7:05 am

Re: filter keys

Postby Wojtek Lerch » Fri Jun 04, 2004 8:47 pm

Alain Bonnefoy wrote:
I've created a region between ROOT and DEVICE to filter some keys but I
reemit the event I don't want to block, nobody receive it.
....
/*
* this is going to be a Raw event, not a key event, because
* we want to emit it rootwards towards the Device region,
* which will consume, focus, and reemit our event as a true
* key event
*/

I don't think this is a good idea. If you re-emit a key event as a raw
key event, Photon will send it back to you, and the event will keep
bouncing between you and Photon forever. The reason you're not seeing
an infinite loop is beacuse there are several mistakes in your code (see
below)...

If you want the event you're re-emitting to look as if your region had
not intercepted it, the best way is by sending the event with the same
type, rectangle, and contents as the event you received. And in the
same direction. In other words, you should just copy collector.rid to
emitter.rid, set collector.rid and translation to zero (because their
meaning in an event you're sending is different than in an event you've
received), and leave the rest untouched.

phEvent.processing_flags = Ph_FAKE_EVENT;

Don't bother setting processing_flags. Photon will reset it to zero.
Besides, your event is not fake -- you are really emitting it.

phEvent.type = Ph_EV_KEY;

The device region is transparent and insensitive to Ph_EV_KEY events.
Raw events have the type Ph_EV_RAW, not Ph_EV_KEY.

phEvent.subtype = Ph_EV_KEY;

Ph_EV_KEY is not a subtype. A raw key event has a subtype of Ph_EV_RAW_KEY.

phEvent.emitter.rid = PtWidgetRid( rcv_region_widget );
phEvent.collector.rid = Ph_ROOT_RID;

Setting collector.rid to a non-zero region ID means "don't give the
event to any region other than this". Incidentally, the root region's
ID is zero, and zero means "give the event to all regions that it hits";
but spelling the zero as Ph_ROOT_RID will be confusing to the next
person who reads your code...

phEvent.input_group = PhInputGroup( NULL );
phEvent.data_len = sizeof( PhKeyEvent_t );

Event data of a raw key event should be a PhRawKeyEvent_t, not a
PhKeyEvent_t.

You're not setting phEvent.flags? Without the TOWARDS flag, the event
will go in the direction of the root region, rather than the device region.

phEvent.num_rects = 1;

/*
* the event's rectangle covers the entire event space;
* this saves us from finding out the extent of the
* collector's region
*/
phEvent_rect.ul.x = phEvent_rect.ul.y = SHRT_MIN;
phEvent_rect.lr.x = phEvent_rect.lr.y = SHRT_MAX;

Key events normally have a one-pixel rectangle. For raw key events, the
rectangle doesn't really matter because the device region covers the
entire Photon space (so you can't miss) and Photon ignores the rectangle
of a received raw event. But for real key events, making the rectangle
bigger than a single dot creates a chance that it'll get received by
more than one window. Of course, that can only happen when you have no
window manager or when it's set to cursor focus, but still...

misc_verbose(verbose, 1, "rid %d\n", (int)phEvent.emitter.rid);
}


Here is how I filter ou the events:

int cbRegionFilterEvent( PtWidget_t *widget, void *data, PtCallbackInfo_t
*cbinfo )
{
PhKeyEvent_t * keyEvent = NULL;

if ( (cbinfo == NULL)
|| (cbinfo->event == NULL) )
return Pt_CONTINUE;

FYI These checks for NULL are not necessary in a filter callback.
Unless you do something silly (like call the function yourself, or set
cbinfo->event to NULL), neither cbinfo nor cbinfo->event can possibly be
NULL. Oh, and I don't think PhGetData() is capable of returning NULL,
either.

switch (cbinfo->event->type) {
case Ph_EV_KEY :

keyEvent = (PhKeyEvent_t*)PhGetData(cbinfo->event);
if (keyEvent == NULL)
return Pt_CONTINUE;

if (keyEvent->key_flags & Pk_KF_Key_Down) {


FYI If you're checking the Sym_Valid flag, there's no need to check
Key_Down, too.

misc_verbose(verbose, 1, "Rcv Key Down\n");

misc_verbose(verbose, 2, " key_mods :
0x%08x\n", (unsigned)keyEvent->key_mods);

if (keyEvent->key_flags & Pk_KF_Sym_Valid) {
misc_verbose(verbose, 2, " key_sym :
0x%08x\n", (unsigned)keyEvent->key_sym);

switch ((unsigned)keyEvent->key_sym) {
....

default:
misc_verbose(verbose, 1, "reemit event\n");
PhEventEmit( &phEvent, &phEvent_rect,
&keyEvent );
break;
}
}
if (keyEvent->key_flags & Pk_KF_Cap_Valid)
misc_verbose(verbose, 2, " key_cap :
0x%08x\n", (unsigned)keyEvent->key_cap);
}
break;

default:
misc_verbose(verbose, 1, "reemit event\n");
PhEventEmit( &phEvent, &phEvent_rect, &keyEvent );
break;
}

return Pt_CONTINUE;
}


What is wrong ?

Thanks,
Alain.

Wojtek Lerch
 

Re: filter keys

Postby alain » Mon Jun 07, 2004 6:05 am

Perfect Wojtek, so simple with your infos.

In fact I wasn't so far in my first attempt except a mistake about the
phEvent to emit.

After it becomes what you discovered in this post ... beurk.

Cheers,
Alain.

Alain Bonnefoy wrote:

I've created a region between ROOT and DEVICE to filter some keys but I
reemit the event I don't want to block, nobody receive it.

This how I create the region:

void CreateRcvRegion(void)
{
PhArea_t area;
PtArg_t arg[20];
short numargs = 0;
long fields;

fields = Ph_REGION_PARENT
| Ph_REGION_EV_SENSE
| Ph_REGION_IN_FRONT
| Ph_REGION_EV_OPAQUE
| Ph_REGION_FLAGS
| Ph_REGION_INPUT_GROUP;
PtSetArg( &arg[numargs++], Pt_ARG_REGION_FIELDS, fields, fields );


area.pos.x = area.pos.y = 0; area.size.w = area.size.h = SHRT_MAX;
PtSetArg( &arg[numargs++], Pt_ARG_AREA, &area, 0 );

PtSetArg( &arg[numargs++], Pt_ARG_REGION_PARENT, Ph_ROOT_RID, 0
);
PtSetArg( &arg[numargs++], Pt_ARG_REGION_SENSE, Ph_EV_KEY,
Ph_EV_KEY);
PtSetArg( &arg[numargs++], Pt_ARG_REGION_OPAQUE, Ph_EV_KEY,
Ph_EV_KEY);
PtSetArg( &arg[numargs++], Pt_ARG_REGION_INPUT_GROUP, 0, 0);
PtSetArg( &arg[numargs++], Pt_ARG_REGION_FLAGS, Ph_KBD_REGION,
Ph_KBD_REGION);
PtSetArg( &arg[numargs++], Pt_ARG_REGION_INFRONT, Ph_DEV_RID, 0
);
PtSetArg( &arg[numargs++], Pt_ARG_FILL_COLOR,
Pg_TRANSPARENT, 0 );

rcv_region_widget = PtCreateWidget( PtRegion, NULL, numargs, arg );
PtAddEventHandler( rcv_region_widget, Ph_EV_KEY, cbRegionFilterEvent,
NULL );
PtRealizeWidget( rcv_region_widget );

/*
* this is going to be a Raw event, not a key event, because
* we want to emit it rootwards towards the Device region,
* which will consume, focus, and reemit our event as a true
* key event
*/
phEvent.processing_flags = Ph_FAKE_EVENT;
phEvent.type = Ph_EV_KEY;
phEvent.subtype = Ph_EV_KEY;
phEvent.emitter.rid = PtWidgetRid( rcv_region_widget );
phEvent.collector.rid = Ph_ROOT_RID;
phEvent.input_group = PhInputGroup( NULL );
phEvent.data_len = sizeof( PhKeyEvent_t );
phEvent.num_rects = 1;

/*
* the event's rectangle covers the entire event space;
* this saves us from finding out the extent of the
* collector's region
*/
phEvent_rect.ul.x = phEvent_rect.ul.y = SHRT_MIN;
phEvent_rect.lr.x = phEvent_rect.lr.y = SHRT_MAX;

misc_verbose(verbose, 1, "rid %dn", (int)phEvent.emitter.rid);
}


Here is how I filter ou the events:

int cbRegionFilterEvent( PtWidget_t *widget, void *data, PtCallbackInfo_t
*cbinfo )
{
PhKeyEvent_t * keyEvent = NULL;

if ( (cbinfo == NULL)
|| (cbinfo->event == NULL) )
return Pt_CONTINUE;

switch (cbinfo->event->type) {
case Ph_EV_KEY :

keyEvent = (PhKeyEvent_t*)PhGetData(cbinfo->event);
if (keyEvent == NULL)
return Pt_CONTINUE;

if (keyEvent->key_flags & Pk_KF_Key_Down) {
misc_verbose(verbose, 1, "Rcv Key Downn");

misc_verbose(verbose, 2, " key_mods :
0x%08xn", (unsigned)keyEvent->key_mods);

if (keyEvent->key_flags & Pk_KF_Sym_Valid) {
misc_verbose(verbose, 2, " key_sym :
0x%08xn", (unsigned)keyEvent->key_sym);

switch ((unsigned)keyEvent->key_sym) {
case T5_KEY_STOP_L:
break;

case T5_KEY_START_L:
break;

case T5_KEY_SLOW_L:
break;

case T5_KEY_TEMP_L:
break;

case T5_KEY_STOP_R:
break;

case T5_KEY_START_R:
break;

case T5_KEY_SLOW_R:
break;

case T5_KEY_TEMP_R:
break;

case T5_KEY_STOP_DOF:
break;

case T5_KEY_START_DOF:
break;

default:
misc_verbose(verbose, 1, "reemit eventn");
PhEventEmit( &phEvent, &phEvent_rect,
&keyEvent );
break;
}
}
if (keyEvent->key_flags & Pk_KF_Cap_Valid)
misc_verbose(verbose, 2, " key_cap :
0x%08xn", (unsigned)keyEvent->key_cap);
}
break;

default:
misc_verbose(verbose, 1, "reemit eventn");
PhEventEmit( &phEvent, &phEvent_rect, &keyEvent );
break;
}

return Pt_CONTINUE;
}


What is wrong ?

Thanks,
Alain.
alain
Active Member
 
Posts: 68
Joined: Tue Apr 27, 2004 7:05 am

RE: Re: filter keys

Postby jinma » Thu Dec 28, 2006 12:52 am

Wojtek Lerch I need your help.
This is what I want to create from PhAB.
Two or more form like windows screen which the user can fill in (like account info with address, phone number, ssn etc)
But this program has two mode, admin and normal. If you are in normal mode there will be certain fields in the form that we can't edit and if you are in admin mode all the fields becomes editable.

One easy way of doing this is when the state changes from admin to user or vise versa, it will call a callback which sets resources for those widgets to be disabled or enabled. But doing it this way, the callback has to know all the name of the widget which belong to admin. So instead, I want my callback to generate custom event (I don't know if there is a such a thing) that only my application can process. So when this custom event is generated and emitted to the event space, all the widgets that are sensitive to this event will call it's callback and disable or enable it self. I like this design because in future when we add more forms (seperate window), I don't have to keep track of all the widgets, instead all those widgets are sensitive to this custom event and call it's callback. Any ideas or help would be appreciated.

Thanks
jinma
Senior Member
 
Posts: 428
Joined: Thu Oct 28, 2004 10:13 pm

Re: filter keys

Postby Joan Baucells » Fri Dec 29, 2006 7:13 am

You can do a callback with a loop that examine all the widgets in a
container.
Than in each widget you can put at design time some data in the user data
field.
Your callback can decide what to do based in this data and the widget
type.
When you add new widgets you only must be aware of the data to place in
the user data field.


jinma wrote:

Wojtek Lerch I need your help.
This is what I want to create from PhAB.
Two or more form like windows screen which the user can fill in (like
account info with address, phone number, ssn etc)
But this program has two mode, admin and normal. If you are in normal
mode there will be certain fields in the form that we can't edit and
if you are in admin mode all the fields becomes editable.

One easy way of doing this is when the state changes from admin to
user or vise versa, it will call a callback which sets resources for
those widgets to be disabled or enabled. But doing it this way, the
callback has to know all the name of the widget which belong to
admin. So instead, I want my callback to generate custom event (I
don't know if there is a such a thing) that only my application can
process. So when this custom event is generated and emitted to the
event space, all the widgets that are sensitive to this event will
call it's callback and disable or enable it self. I like this design
because in future when we add more forms (seperate window), I don't
have to keep track of all the widgets, instead all those widgets are
sensitive to this custom event and call it's callback. Any ideas or
help would be appreciated.

Thanks
Joan Baucells
 

RE: Re: filter keys

Postby jinma » Tue Jan 02, 2007 5:45 pm

sounds like a plan but can you show example of this callback? And when will this callback be invoked? at what event?
Thanks
jinma
Senior Member
 
Posts: 428
Joined: Thu Oct 28, 2004 10:13 pm


Return to qnx.gui

Who is online

Users browsing this forum: No registered users and 1 guest