filter keys

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 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.

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.

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

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

sounds like a plan but can you show example of this callback? And
when will this callback be invoked? at what event?
Thanks