/* This input filter will handle zaurus-specific keyboard events, like * powering off and adjusting the frontlight. */ void infilter_zaurus_handler(struct infilter *self, u32 trigger, union trigparam *param) { static u32 last_cancel_press = 0; u32 now; union trigparam newtrig; switch (param->kbd.key) { /* Detect double-press of the cancel button as suspend */ case PGKEY_ESCAPE: now = os_getticks(); if (now < last_cancel_press + 250) drivermessage(PGDM_POWER, PG_POWER_SLEEP, NULL); else last_cancel_press = now; break; /* Seems to be F6 is what happens when you press Fn-C, map that to CTRL-C */ case PGKEY_F6: newtrig = *param; newtrig.kbd.key = PGKEY_c; newtrig.kbd.mods = PGMOD_CTRL; infilter_send(self,PG_TRIGGER_KEY,&newtrig); break; } }
void infilter_magic_handler(struct infilter *self, u32 trigger, union trigparam *param) { /* If a CTRL-ALT key was pressed, the keydown event triggers magic_button. * Otherwise, pass on the key. */ if ((param->kbd.mods & PGMOD_CTRL) && (param->kbd.mods & PGMOD_ALT)) { if (trigger==PG_TRIGGER_KEYDOWN) magic_button(param->kbd.key); } else infilter_send(self,trigger,param); }
void infilter_hotspot_handler(struct infilter *self, u32 trigger, union trigparam *param) { int consume = 0; /* Traverse the hotspot graph using keys defined in the theme */ if (!(param->kbd.mods & ~(PGMOD_CAPS|PGMOD_NUM))) { /* Key down, no modifiers */ if (param->kbd.key == hotkey_next) { consume = 1; if (trigger==PG_TRIGGER_KEYDOWN) hotspot_traverse(HOTSPOT_NEXT); } else if (param->kbd.key == hotkey_up) { consume = 1; if (trigger==PG_TRIGGER_KEYDOWN) hotspot_traverse(HOTSPOT_UP); } else if (param->kbd.key == hotkey_down) { consume = 1; if (trigger==PG_TRIGGER_KEYDOWN) hotspot_traverse(HOTSPOT_DOWN); } else if (param->kbd.key == hotkey_left) { consume = 1; if (trigger==PG_TRIGGER_KEYDOWN) hotspot_traverse(HOTSPOT_LEFT); } else if (param->kbd.key == hotkey_right) { consume = 1; if (trigger==PG_TRIGGER_KEYDOWN) hotspot_traverse(HOTSPOT_RIGHT); } } else if (!(param->kbd.mods & ~(PGMOD_CAPS|PGMOD_NUM|PGMOD_SHIFT))) { /* Key down with shift */ if (param->kbd.key == hotkey_next) { consume = 1; if (trigger==PG_TRIGGER_KEYDOWN) hotspot_traverse(HOTSPOT_PREV); } } /* Pass it on if we didn't use it */ if (!consume) infilter_send(self,trigger,param); }
/* Given a pg_client_trigger in network byte order this will reconstruct * the trigparam union from it, and dispatch it to the proper input filter. */ g_error infilter_client_send(union pg_client_trigger *client_trig) { union trigparam tp; int i; struct infilter *from; g_error e; memset(&tp,0,sizeof(tp)); /* Convert it all to host byte order */ for (i=0;i<(sizeof(client_trig->array)/sizeof(client_trig->array[0]));i++) client_trig->array[i] = ntohl(client_trig->array[i]); /* Reconstruct the trigparam union, depending on trigger type */ if (client_trig->content.type & PG_TRIGGERS_KEY) { tp.kbd.key = client_trig->content.u.kbd.key; tp.kbd.mods = client_trig->content.u.kbd.mods; tp.kbd.flags = client_trig->content.u.kbd.flags; tp.kbd.consume = client_trig->content.u.kbd.consume; tp.kbd.divtree = client_trig->content.u.kbd.divtree; } else if (client_trig->content.type & PG_TRIGGERS_MOUSE) { tp.mouse.x = client_trig->content.u.mouse.x; tp.mouse.y = client_trig->content.u.mouse.y; tp.mouse.btn = client_trig->content.u.mouse.btn; tp.mouse.chbtn = client_trig->content.u.mouse.chbtn; tp.mouse.pressure = client_trig->content.u.mouse.pressure; tp.mouse.is_logical = client_trig->content.u.mouse.is_logical; tp.mouse.divtree = client_trig->content.u.mouse.divtree; e = rdhandle((void**)&tp.mouse.cursor, PG_TYPE_CURSOR, -1, client_trig->content.u.mouse.cursor_handle); tp.mouse.ts_calibration = client_trig->content.u.mouse.ts_calibration; errorcheck; } else if (client_trig->content.type & PG_TRIGGER_MOTIONTRACKER) { memcpy(&tp.motion, &client_trig->content.u.motion, sizeof(tp.motion)); } /* Get the source infilter */ e = rdhandle((void**)&from,PG_TYPE_INFILTER,-1,client_trig->content.infilter_from); errorcheck; /* Send it out */ infilter_send(from, client_trig->content.type, &tp); return success; }
void infilter_pntr_dispatch_handler(struct infilter *self, u32 trigger, union trigparam *param) { struct widget *under; int release_captured = 0; int accepted = 0; /* In order to dispatch a pointing event, it must have an associated cursor. * The normalize filter should have given us a cursor whether the driver had * one or not, but in case an event was inserted into the pipe with no cursor, * pass it on. This will usually just run the event off the end of the * filter chain, but this makes it theoretically possible for a client to pick * up the cursorless events. */ if (!param->mouse.cursor) { infilter_send(self, trigger, param); return; } /* Move the cursor */ if (trigger==PG_TRIGGER_MOVE) { int cx,cy; struct divtree *new_dt, *old_dt; /* Default to the topmost divtree, but allow the event to override */ if (iserror(rdhandle((void**)&new_dt, PG_TYPE_DIVTREE, -1, param->mouse.divtree)) || !new_dt) new_dt = dts->top; /* If the cursor is already at the destination, throw away this event */ cursor_getposition(param->mouse.cursor,&cx,&cy,&old_dt); if (cx == param->mouse.x && cy == param->mouse.y && new_dt == old_dt) return; cursor_move(param->mouse.cursor,param->mouse.x,param->mouse.y,new_dt); } inactivity_reset(); /* Read which widget is under the cursor */ under = NULL; rdhandle((void**)&under, PG_TYPE_WIDGET, -1, param->mouse.cursor->ctx.widget_under); /* If the capture_btn is released, release the capture */ if ((!(param->mouse.btn & param->mouse.cursor->ctx.capture_btn)) && param->mouse.cursor->ctx.widget_capture && param->mouse.cursor->ctx.widget_capture != param->mouse.cursor->ctx.widget_under) { struct widget *capture; if ((!iserror(rdhandle((void**)&capture, PG_TYPE_WIDGET, -1, param->mouse.cursor->ctx.widget_capture))) && capture) release_captured = send_trigger(capture,PG_TRIGGER_RELEASE,param); accepted++; param->mouse.cursor->ctx.widget_capture = 0; param->mouse.cursor->ctx.capture_btn = 0; } if (under) { /* There's an interactive widget under the cursor */ /* Keep track of the most recently clicked widget */ if (trigger==PG_TRIGGER_DOWN) { param->mouse.cursor->ctx.widget_last_clicked = param->mouse.cursor->ctx.widget_under; /* Also, allow clicks to focus applications */ appmgr_focus(appmgr_findapp(under)); } /* First send the 'raw' event, then handle the cooked ones. */ if (!release_captured) accepted += send_propagating_trigger(under,trigger,param); /* If the mouse is clicked in a widget, it 'captures' future MOVE and RELEASE events * until this button is released. */ if (trigger==PG_TRIGGER_DOWN && !param->mouse.cursor->ctx.widget_capture) { param->mouse.cursor->ctx.widget_capture = param->mouse.cursor->ctx.widget_under; param->mouse.cursor->ctx.capture_btn = param->mouse.chbtn; } } /* If a captured widget accepts PG_TRIGGER_DRAG, send it even when the * mouse is outside its divnodes. */ if (trigger==PG_TRIGGER_MOVE && param->mouse.cursor->ctx.widget_capture) { struct widget *capture; if ((!iserror(rdhandle((void**)&capture, PG_TYPE_WIDGET, -1, param->mouse.cursor->ctx.widget_capture))) && capture) accepted += send_trigger(capture,PG_TRIGGER_DRAG,param); } /* If nothing has accepted the event so far, pass it on */ if (!accepted) infilter_send(self,trigger,param); }
void infilter_pntr_normalize_handler(struct infilter *self, u32 trigger, union trigparam *param) { int x,y, oldbtn, newbtn; static struct cursor *cursor_global_invisible; /* If we have pointer events with no cursor, assign them our invisible global * cursor so that it can collect context information that we'll need for dispatch. */ if (!param->mouse.cursor) { if (!cursor_global_invisible) { if (iserror(cursor_new(&cursor_global_invisible,NULL,-1))) return; cursor_global_invisible->sprite->visible = 0; } param->mouse.cursor = cursor_global_invisible; } if (trigger != PG_TRIGGER_SCROLLWHEEL) { /* Get physical cursor position for use later */ cursor_getposition(param->mouse.cursor, &x, &y,NULL); if (!param->mouse.is_logical) { /* Normal rotation handling */ VID(coord_physicalize)(&x,&y); } /* Convert relative motion to absolute motion. * We have to be careful about which coordinate system the input is in. */ if (trigger==PG_TRIGGER_PNTR_RELATIVE) { trigger = PG_TRIGGER_PNTR_STATUS; param->mouse.x += x; param->mouse.y += y; if (param->mouse.is_logical) VID(coord_physicalize)(&x,&y); param->mouse.is_logical = 0; } /* Convert absolute motion to individual events */ if (trigger==PG_TRIGGER_PNTR_STATUS) { /* Save the old/new button state too, since it may be modified by other * input filters when we do infilter_send. Remember that this is all working * with the same trigparam structure, and just repassing it after changing * the type :) */ newbtn = param->mouse.btn; oldbtn = param->mouse.cursor->prev_buttons; if (newbtn & ~oldbtn) trigger = PG_TRIGGER_DOWN; else if (oldbtn & ~newbtn) trigger = PG_TRIGGER_UP; else trigger = PG_TRIGGER_MOVE; } /* If we're moving the cursor and this isn't a MOVE event, generate one */ if ((param->mouse.x != x || param->mouse.y != y) && trigger!=PG_TRIGGER_MOVE) { union trigparam moveparam = *param; moveparam.mouse.btn = param->mouse.cursor->prev_buttons; infilter_send(self,PG_TRIGGER_MOVE,&moveparam); } } /* Detect changes in buttons, and store that along with the event */ param->mouse.chbtn = param->mouse.btn ^ param->mouse.cursor->prev_buttons; param->mouse.cursor->prev_buttons = param->mouse.btn; /* Resend it (we might have changed the trigger type) */ infilter_send(self,trigger,param); }