________________________________________________________________________
Applicable Environment
________________________________________________________________________
- Topic: Photon: Control mouse pointer without mouse
- SDP: 6.4.1
- Host/Target: Any supported target
________________________________________________________________________
Recommendation________________________________________________________________________
This needs a little effort, since clicking a mousebutton is not as trivial as it may seem. Especially to tell a click and a drag apart. The main function move the mouse pointer is:
PhMoveCursorRel( 1, dx, dy )
This is some example code to demonstrate 'smooth' movements with variable speed:
---->
/*
* Helperfunction to emulate mouse buttons
*/
static void EmitPtrEvent( int ig, unsigned long type, unsigned short
subtype,
unsigned short button_state, PhPoint_t *pos ) {
PhPointerEvent_t pev;
PhEvent_t event;
PhRect_t rect;
short x, y;
PtGetAbsPosition( ABW_base, &x, &y );
memset( &event, 0, sizeof event );
event.type = type;
event.subtype = subtype;
event.processing_flags = 0;
event.emitter.rid = 1;
event.emitter.handle = 0;
event.input_group = 1;
event.flags = 0;
event.timestamp = time( NULL );
event.translation.x = -x;
event.translation.y = -y;
event.num_rects = 1;
event.data_len = sizeof pev +1;
pev.pos = *pos;
pev.click_count = 1;
pev.z = 0;
pev.flags = 0;
pev.button_state = button_state;
pev.buttons = Ph_BUTTON_SELECT;
pev.key_mods = 0;
rect.ul =
rect.lr = *pos;
PhEventEmit( &event, &rect, &pev );
}
/*
* The actual Emulation. A TimerEvent controls the updates, either
* movement or click. Most of the code is handling the delta
* values to realize a smooth movement.
*/
static int TmrActivateCb( PtWidget_t *widget, void *data, PtCallbackInfo_t
*cbinfo ) {
PhCursorInfo_t info;
PtWidget_t *tgt_wgt;
PhArea_t tgt_area;
double d, h;
short x, y;
int cur_x, cur_y;
int tgt_x, tgt_y;
int dx, dy;
int v; // desired velocity
/* eliminate 'unreferenced' warnings */
widget = widget, data = data, cbinfo = cbinfo;
if ( TgtIdx >= NumSimWgts )
return Pt_CONTINUE;
PhQueryCursor( 1, &info );
switch ( State ) {
case 0: // Movement - see below
break;
case 1: // Button press
EmitPtrEvent( cbinfo->event->input_group, Ph_EV_BUT_PRESS, 0,
Ph_BUTTON_SELECT, &info.pos );
State++;
return Pt_CONTINUE;
case 2: // Button release
// Release with current mouse position
EmitPtrEvent( cbinfo->event->input_group, Ph_EV_BUT_RELEASE,
Ph_EV_RELEASE_REAL, 0, &info.pos );
// Release with mouse position when button was pressed
EmitPtrEvent( cbinfo->event->input_group, Ph_EV_BUT_RELEASE,
Ph_EV_RELEASE_PHANTOM, 0, &info.pos );
// Single click, don't wait for another
EmitPtrEvent( cbinfo->event->input_group, Ph_EV_BUT_RELEASE,
Ph_EV_RELEASE_ENDCLICK, 0, &info.pos );
State = 0;
if ( ++TgtIdx >= NumSimWgts )
Sims_Stop();
return Pt_CONTINUE;
}
tgt_wgt = SimWgts[TgtIdx];
cur_x = info.pos.x;
cur_y = info.pos.y;
PtWidgetArea( tgt_wgt, &tgt_area );
PtGetAbsPosition( tgt_wgt, &x, &y );
tgt_area.pos.x = x;
tgt_area.pos.y = y;
tgt_x = x + ( tgt_area.size.w / 2 );
tgt_y = y + ( tgt_area.size.h / 2 );
dx = tgt_x - cur_x;
dy = tgt_y - cur_y;
d = hypot( dx, dy );
h = RadNorm( atan2( dy, dx ) );
if ( d < 5 ) {
if ( ( cur_x >= tgt_area.pos.x ) && ( cur_x < tgt_area.pos.x +
tgt_area.size.w )
&& ( cur_y >= tgt_area.pos.y ) && ( cur_y < tgt_area.pos.y +
tgt_area.size.h ) ) {
State = 1;
return Pt_CONTINUE;
}
}
v = sqrt( .25 + 2 * d ) - 0.5;
if ( v > Velocity ) {
if ( ( Velocity += 5 ) > v )
Velocity = v;
}
else if ( v < Velocity )
Velocity -= 1;
if ( h > Heading ) {
if ( fabs( h - Heading ) < PI )
Heading += ( h - Heading ) / 3;
else
Heading = RadNorm( Heading - ( ( PI2 - h + Heading ) / 3 ) );
}
else {
if ( fabs( Heading - h ) < PI )
Heading -= ( Heading - h ) / 3;
else
Heading = RadNorm( Heading + ( ( PI2 + h - Heading ) / 3 ) );
}
dx = cos( Heading ) * Velocity;
dy = sin( Heading ) * Velocity;
PhMoveCursorRel( 1, (int) dx, (int) dy );
return Pt_CONTINUE;
}
<----
________________________________________________________________________
NOTE:
This entry has been validated against the SDP version listed above. Use
caution when considering this advice for any other SDP version. For
supported releases, please reach out to QNX Technical Support if you have any questions/concerns. ________________________________________________________________________