Dean Douthat <ddouthat@faac.com> wrote:
We are trying to write an application that receives messages from
another (non-Photon) process and also needs to catch keystrokes from the
keyboard. So far, we are using PtAppAddInput to add an input handler
that does the other messages. How do we go about catching keystrokes?
Create (from code - you can’t do it in PhAB - see “Creating
Widgets in Application Code” in the Photon Programmer’s Guide) a
PtRegion widget owned by your application that sits on the root
side of the Device Region. Make it sensitive to keyboard events
(and non-opaque to them too, if you don’t want to block keyboard
events to all other applications. Attach (again from code) a
filter or raw callback to the PtRegion, and grab your keyboard
events there. There’s a bit on emitting key events in the Events
section of the Programmer’s Guide which will help you understand
what you’re looking at.
This is very brief (the current (QNX 6) Photon Advanced course
covers this general topic in about 100 pages…), but if you work
through the “Photon Architecture”, “Regions” and “Events”
chapters of the 1.14 Programmer’s Guide, you should be able to
get enough background to see what I’m on about above.
We found function PtReadEvent but don’t quite know how to invoke it
since we don’t seem to be able to get a callback when using PtMainLoop.
Should we make our own main loop? Or is there another way to get called
back. We are using PhAB.
You definitely don’t need your own main loop. Go with the
PtRegion + Raw (or Filter) callback approach.
Just on the chance it will help, I’ll drop in the callback code
from two of the samples from the Advanced Photon course. Note
that this is QNX6 code, and neither does quite what you want.
Still, it should show you a few of the tricks involved.
Hope this helps.
Norbert Black
QSSL Training Services
********** code from “emitter” begins **************************
/* callbacks.c
This application demonstrates the use of the PtRegion
widget.
This file contains:
base_btn_createregion_activateCB()
Callback type: Pt_CB_ACTIVATE
Widget: base_btn_createregion
This function demonstrates how to create a region
using the PtRegion widget. Its parent is set to
be the Device region, which puts the widget closer
to the user than that region.
base_btn_emitQ_activateCB()
Callback type: Pt_CB_ACTIVATE
Widget: base_btn_emitQ
This function shows how to emit both key down and key
up events as raw key events to be focused, consumed
and remitted by the Device region. The events are
emitted towards the root region.
\
/
/ Standard headers */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
/* Toolkit headers */
#include <Ph.h>
#include <Pt.h>
#include <Ap.h>
/* Local headers /
#include “abimport.h”
#include “proto.h”
/***************************
*** global variables ***
**************************/
PtWidget_t region_widget = NULL;
/--------------------------------------------------------------------
*
- base_btn_createregion_activateCB
-
--------------------------------------------------------------------/
int
base_btn_createregion_activateCB( PtWidget_t *widget, ApInfo_t *apinfo,
PtCallbackInfo_t *cbinfo )
{
PhArea_t area;
PtArg_t arg[20];
short nargs = 0;
long fields;
fields = Ph_REGION_FLAGS |
Ph_REGION_OWNER |
Ph_REGION_PARENT;
/*
- this specifies which resources we are setting below.
*‘fields’ is set above. Be sure to update the list if you
- change which resources are being set.
/
PtSetArg( &arg[nargs++], Pt_ARG_REGION_FIELDS, fields, fields );
/
- parent is the Device region; this will put our new
- region closer to the user than that region
/
PtSetArg( &arg[nargs++], Pt_ARG_REGION_PARENT, Ph_DEV_RID, 0 );
/
- owner is our process; we set this so that we can recognize
- the region as belonging to us when we use the “phin” tool
*/
PtSetArg( &arg[nargs++], Ph_REGION_OWNER,
PtWidgetRid( ABW_base ), 0 );
/*
- our region should be a keyboard region, since we’ll be using
- it to emit key-related events
/
PtSetArg( &arg[nargs++], Pt_ARG_REGION_FLAGS,
Ph_KBD_REGION, Ph_KBD_REGION );
/
- we want our region to cover the visible x/y plane, which
- extends from 0 to SHRT_MAX along both axes; setting Pt_ARG_AREA
- causes Pt_ARG_REGION_ORIGIN and Pt_ARG_REGION_RECT to be set
- accordingly
/
area.pos.x = area.pos.y = 0;
area.size.w = area.size.h = -(SHRT_MIN) + SHRT_MAX;
PtSetArg( &arg[nargs++], Pt_ARG_AREA, &area, 0 );
/
- we’ll make the region have a transparent fill color so
- we can see through it…
*/
PtSetArg( &arg[nargs++], Pt_ARG_FILL_COLOR, Pg_TRANSPARENT, 0 );
/*
- create the widget
/
if( ( region_widget = PtCreateWidget( PtRegion, Pt_NO_PARENT,
nargs, arg ) )
== NULL )
{
perror( “emitter: failed PtCreateWidget()” );
return( Pt_CONTINUE );
}
/
- put the widget into Photon event space
/
if( ( PtRealizeWidget( region_widget ) ) == -1 )
{
perror( “emitter: failed PtRealizeWidget()” );
return( Pt_CONTINUE );
}
/
- disable this button so that we don’t have more than one
- dynamically created PtRegion
*/
nargs = 0;
PtSetArg( &arg[nargs++], Pt_ARG_FLAGS, Pt_GHOST,
Pt_GETS_FOCUS |Pt_GHOST | Pt_SELECTABLE );
PtSetResources( widget, nargs, arg );
/*
- enable the “Emit a Q” button, which requires our new region
- to do its work
*/
nargs = 0;
PtSetArg( &arg[nargs++], Pt_ARG_FLAGS,
Pt_GETS_FOCUS |Pt_SELECTABLE,
Pt_GETS_FOCUS |Pt_GHOST | Pt_SELECTABLE );
PtSetResources( ABW_base_btn_emitQ, nargs, arg );
/* eliminate ‘unreferenced’ warnings */
widget = widget, apinfo = apinfo, cbinfo = cbinfo;
return( Pt_CONTINUE );
}
/--------------------------------------------------------------------
*
- base_btn_emitQ_activateCB
-
--------------------------------------------------------------------/ int
base_btn_emitQ_activateCB( PtWidget_t *widget, ApInfo_t *apinfo,
PtCallbackInfo_t *cbinfo )
{
PhEvent_t event;
PhRawKeyEvent_t key_data;
PhRect_t event_rect;
memset( &event, 0, sizeof( event ) );
memset( &key_data, 0, sizeof( key_data ) );
/*
- 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
*/
event.type = Ph_EV_RAW;
event.subtype = Ph_EV_RAW_KEY;
event.emitter.rid = PtWidgetRid( region_widget );
event.collector.rid = Ph_DEV_RID;
event.input_group = PhInputGroup( NULL );
event.data_len = sizeof( key_data );
event.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
/
event_rect.ul.x = event_rect.ul.y = SHRT_MIN;
event_rect.lr.x = event_rect.lr.y = SHRT_MAX;
/
- describe the key involved in this event
/
key_data.key_cap = Pk_q; / we’re using the “q” /
key_data.key_sym = Pk_Q; / modified, it’s a “Q” /
key_data.key_mods = Pk_KM_Shift; / these are the modifiers used */
/*
- emit key down
/
key_data.key_flags = Pk_KF_Key_Down | Pk_KF_Sym_Valid |
Pk_KF_Cap_Valid;
PhEventEmit( &event, &event_rect, &key_data );
/
- emit key up - note that we toggle the status of the key_down
- field - it must be clear for this event to be recognised as
- a key up event
/
key_data.key_flags &= ~(Pk_KF_Key_Down);
PhEventEmit( &event, &event_rect, &key_data );
/ eliminate ‘unreferenced’ warnings */
widget = widget, apinfo = apinfo, cbinfo = cbinfo;
return( Pt_CONTINUE );
}
********** code from “ptregion” begins **************************
/* callbacks.c /
/ /
/ This application demonstrates the use of the PtRegion /
/ widget. /
/ /
/ IMPORTANT: We are setting the parent region using /
/ Pt_ARG_REGION_PARENT and setting the region that is /
/ front of our region using Pt_ARG_REGION_INFRONT. The /
/ parent is being set to the root region (Ph_ROOT_RID) /
/ and the region in front is being set to the device /
/ region (Ph_DEV_RID). By saying that we want the /
/ device region to be in front we are also saying that /
/ we want it to be our brother. Well, if the device /
/ region is to be our brother then it’s parent had /
/ better also be the same are our parent (the root /
/ region). /
/ /
/ This file contains: /
/ /
/ base_btn_createregion_activateCB() /
/ Callback type: Pt_CB_ACTIVATE /
/ Widget: base_btn_createregion /
/ /
/ This function demonstrates how to create a region /
/ using the PtRegion widget. /
/ /
/-------------------------------------------------------/
/ /
/ eventsCB() /
/ Callback type: Pt_CB_RAW /
/ Widget: the PtRegion created in /
/ createRegionCB() /
/ /
/ This simply prints out that it got an event. /
/ /
/-------------------------------------------------------/
/ /
/ PhotonGetWindowPosn() /
/ Function type: called by createRegionCB() /
/ Widget: none /
/ /
/ This function returns the absolute coordinates of /
/ the top,left corner of the base window’s frame and /
/ the size inside the frame. /
/ /
/ Operation: /
/ /
/ To get the size this simply gets the value of the /
/ Pt_ARG_DIM resource. /
/ /
/ To get the coordinates this calls /
/ PtGetAbsPosition() to get the absolute position /
/ of the window inside the frame. It then calls /
/ PtWindowFrameSize() to get the height and width /
/ of the frame. Next, it subtracts the frame /
/ height from the absolute y coordinate inside the /
/ frame to get the absolute y coordiante of the /
/ frame. It does the same for the x coordinate. /
/ /
/ AppBuilder Photon Code Lib /
/ Version 1.11B */
/* Standard headers */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
/* Toolkit headers */
#include <Ph.h>
#include <Pt.h>
#include <Ap.h>
/* Local headers /
#include “abimport.h”
#include “proto.h”
/***************************
*** global variables ***
**************************/
PtWidget_t regionWidget;
/--------------------------------------------------------------------
*
- base_btn_createregion_activateCB
-
--------------------------------------------------------------------/
int
base_btn_createregion_activateCB( PtWidget_t *widget, ApInfo_t *apinfo,
PtCallbackInfo_t *cbinfo )
{
PhArea_t area;
PtArg_t arg[20];
short numargs = 0;
long fields;
fields =
//Ph_REGION_ORIGIN
//Ph_REGION_RECT
Ph_REGION_PARENT
//Ph_REGION_HANDLE
//Ph_REGION_OWNER
|Ph_REGION_EV_SENSE
//Ph_REGION_EV_OPAQUE
|Ph_REGION_IN_FRONT
|Ph_REGION_INPUT_GROUP
;
/*
- this specifies which resources we are setting below.
- ‘fields’ is set above. Be sure to update the list if you change
- which resources are being set.
*/
PtSetArg( &arg[numargs++], Pt_ARG_REGION_FIELDS, fields, fields );
/*
- the position and size of the region will be the same as the
- window. PhotonGetWindowPosn() is a function written below
*/
PhotonGetWindowPosn( ABW_base, &area.pos.y, &area.pos.x,
&area.size.h, &area.size.w );
/*
- setting Pt_ARG_AREA causes Pt_ARG_REGION_ORIGIN and
- Pt_ARG_REGION_RECT to be set accordingly
*/
PtSetArg( &arg[numargs++], Pt_ARG_AREA, &area, 0 );
/*
- parent is the root region. Necessary because child
- regions only get events for the areas of their region that
- overlaps their parent’s region. If we used the base
- window’s region then we would only get events that are in
- the area when the child region and the base window overlap.
- The root region, however, the covers all possible areas and
- so we get events for our entire region no matter where it is.
*/
PtSetArg( &arg[numargs++], Pt_ARG_REGION_PARENT, Ph_ROOT_RID, 0 );
/*
- this region is sensitive only to key events
*/
PtSetArg( &arg[numargs++], Pt_ARG_REGION_SENSE, Ph_EV_KEY,
Ph_EV_KEY );
/*
- this region is opaque only to key events
*/
//PtSetArg( &arg[numargs++], Pt_ARG_REGION_OPAQUE,
// Ph_EV_KEY, Ph_EV_KEY );
/*
- the device region will be in front of our region (i.e.
- we will be behind the device region
*/
PtSetArg( &arg[numargs++], Pt_ARG_REGION_INFRONT, Ph_DEV_RID, 0 );
/*
- this defaults to 0
*/
PtSetArg( &arg[numargs++], Pt_ARG_REGION_INPUT_GROUP,
cbinfo->event->input_group, 0 );
PtSetArg( &arg[numargs++], Pt_ARG_FILL_COLOR, Pg_GREEN, 0 );
regionWidget = PtCreateWidget( PtRegion, NULL, numargs, arg );
PtAddEventHandler( regionWidget, Ph_EV_KEY, eventsCB, NULL );
PtRealizeWidget( regionWidget );
/*
- disable this button so that we don’t have more than one
- dynamically created PtRegion
/
numargs = 0;
PtSetArg( &arg[numargs++], Pt_ARG_FLAGS, Pt_GHOST,
Pt_GETS_FOCUS |Pt_GHOST | Pt_SELECTABLE );
PtSetResources( widget, numargs, arg );
/ eliminate ‘unreferenced’ warnings */
widget = widget, apinfo = apinfo, cbinfo = cbinfo;
return( Pt_CONTINUE );
}
/--------------------------------------------------------------------
*
-------------------------------------------------------------------/
int
eventsCB (PtWidget_t *widget, void *data, PtCallbackInfo_t *cbinfo)
{
printf( “got an event\n” );
/* eliminate ‘unreferenced’ warnings */
widget = widget, data = data, cbinfo = cbinfo;
return( Pt_CONTINUE );
}
/--------------------------------------------------------------------
*
-------------------------------------------------------------------/
void
PhotonGetWindowPosn (PtWidget_t *window, short *top, short *left,
unsigned short *height, unsigned short *width)
{
PtArg_t arg[1];
PhPoint_t *dim;
PhRect_t window_rect;
int framebottom, frameleft, frameright, frametop;
short xpos, ypos;
PtSetArg( &arg[0], Pt_ARG_DIM, &dim, 0 );
PtGetResources( window, 1, arg );
PtGetAbsPosition( window, &xpos, &ypos );
PtWindowFrameSize( NULL, window, &window_rect );
frametop = window_rect.ul.y;
framebottom = window_rect.lr.y;
frameleft = window_rect.ul.x;
frameright = window_rect.lr.x;
*top = ypos - frametop;
*left = xpos - frameleft;
*height = dim->y + frametop + framebottom;
*width = dim->x + frameleft + frameright;
}