/* A widget has requested focus... Send out the ACTIVATE and DEACTIVATE triggers, and update necessary vars */ void request_focus(struct widget *self) { handle hself = hlookup(self,NULL); struct widget *kbdfocus; /* Already focused? */ if (dts->top->focus==hself) return; kbdfocus = NULL; rdhandle((void**)&kbdfocus,PG_TYPE_WIDGET,-1,dts->top->focus); /* Deactivate the old widget, activate the new */ send_trigger(kbdfocus,PG_TRIGGER_DEACTIVATE,NULL); dts->top->focus = hself; appmgr_focus(appmgr_findapp(self)); send_trigger(self,PG_TRIGGER_ACTIVATE,NULL); /* Scroll in */ scroll_to_divnode(self->in->div); /* If there's an active hotspot cursor, move it to this widget */ if (dts->top->hotspot_cursor) { int x,y; divnode_hotspot_position(self->in->div, &x, &y); cursor_move(dts->top->hotspot_cursor,x,y,dts->top); } }
/* Change the number of mouse cursors in the widget, sending out enter/leave events */ void cursor_update_widget(struct widget *w, u8 new_numcursors) { if (new_numcursors && !w->numcursors) send_trigger(w,PG_TRIGGER_ENTER,NULL); if (!new_numcursors && w->numcursors) send_trigger(w,PG_TRIGGER_LEAVE,NULL); w->numcursors = new_numcursors; }
/* Send a trigger that propagates to a widget's container until it's accepted */ int send_propagating_trigger(struct widget *w, s32 type, union trigparam *param) { while (w && !send_trigger(w,type,param)) w = widget_traverse(w,PG_TRAVERSE_CONTAINER,1); if (w) return 1; return 0; }
/* Set the number of cursors occupying the widget, and send any appropriate * triggers due to the change. */ void widget_set_numcursors(struct widget *self, int num, struct cursor *crsr) { union trigparam param; /* Don't let our puny little u8 roll over if something else f***s up */ if (num < 0) num = 0; cursor_getposition(crsr, ¶m.mouse.x, ¶m.mouse.y, NULL); param.mouse.btn = crsr->prev_buttons; param.mouse.chbtn = 0; param.mouse.cursor = crsr; if (self->numcursors && !num) send_trigger(self,PG_TRIGGER_LEAVE,¶m); if (!self->numcursors && num) send_trigger(self,PG_TRIGGER_ENTER,¶m); self->numcursors = num; }
// Looks at the current state and launches the next trigger static int handle_next_event (ctx_t *ctx) { zhash_t *timers; sim_state_t *sim_state = ctx->sim_state; int rc = 0; // get the timer hashtable, make sure its full, and get a list of its keys timers = sim_state->timers; if (zhash_size (timers) < 1) { flux_log (ctx->h, LOG_ERR, "timer hashtable has no elements"); return -1; } // Get the next occuring event time/module double min_event_time = -1; double *curr_event_time = NULL; const char *mod_name = NULL, *curr_name = NULL; for (curr_event_time = zhash_first (timers); curr_event_time; curr_event_time = zhash_next (timers)) { curr_name = zhash_cursor (timers); if (min_event_time < 0 || occurs_before (*curr_event_time, min_event_time) || breaks_tie (*curr_event_time, min_event_time, curr_name)) { min_event_time = *curr_event_time; mod_name = curr_name; } } if (min_event_time < 0) { return -1; } // advance time then send the trigger to the module with the next event if (min_event_time > sim_state->sim_time) { // flux_log (ctx->h, LOG_DEBUG, "Time was advanced from %f to %f while // triggering the next event for %s", // sim_state->sim_time, *min_event_time, mod_name); sim_state->sim_time = min_event_time; } else { // flux_log (ctx->h, LOG_DEBUG, "Time was not advanced while triggering // the next event for %s", mod_name); } flux_log (ctx->h, LOG_DEBUG, "Triggering %s. Curr sim time: %f", mod_name, sim_state->sim_time); rc = send_trigger (ctx->h, mod_name, sim_state); return rc; }
/* * Main routine to process command line options. */ int main(int argc, char **argv) { int ch; unsigned int trigger = 0; if (argc != 2) usage(); while ((ch = getopt(argc, argv, "einst")) != -1) { switch(ch) { case 'e': trigger = AUDIT_TRIGGER_EXPIRE_TRAILS; break; case 'i': trigger = AUDIT_TRIGGER_INITIALIZE; break; case 'n': trigger = AUDIT_TRIGGER_ROTATE_USER; break; case 's': trigger = AUDIT_TRIGGER_READ_FILE; break; case 't': trigger = AUDIT_TRIGGER_CLOSE_AND_DIE; break; case '?': default: usage(); break; } } if (send_trigger(trigger) < 0) exit(-1); printf("Trigger sent.\n"); exit (0); }
/* Sends a trigger to all of a widget's children */ void r_send_trigger(struct widget *w, s32 type, union trigparam *param, int *stop,int forward) { struct widget *bar; if (!w || (*stop) > 0) return; send_trigger(w,type,param); /* Also traverse the panelbar if there is one */ if (!iserror(rdhandle((void**)&bar, PG_TYPE_WIDGET, w->owner, widget_get(w,PG_WP_PANELBAR))) && bar) { r_send_trigger(bar, type, param, stop,0); if ((*stop) > 0) return; } r_send_trigger(widget_traverse(w,PG_TRAVERSE_CHILDREN,0),type,param,stop,1); if (forward) r_send_trigger(widget_traverse(w,PG_TRAVERSE_FORWARD,1),type,param,stop,1); }
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 trigger(void *cvoid, zctx_t * context, void * control) { triggerconfig_t * c = (triggerconfig_t*) cvoid; //set up msgpack stuff zclock_log("watch_port started!"); msgpack_zone mempool; msgpack_zone_init(&mempool, 2048); // TODO char * user_id = "17"; // TODO get broker in somehow char * broker = "tcp://au.ninjablocks.com:5773"; mdcli_t * client = mdcli_new(broker, 1); //VERBOSE triggermemory_t trigger_memory; msgpack_object * addins_obj = parse_msgpack(&mempool, c->addins); if(!parse_addins(addins_obj, &trigger_memory)) { //bad message zclock_log("bad trigger definition"); msgpack_object_print(stdout, *addins_obj); send_sync("bad trigger", control); return; } zclock_log("Creating trigger: target %s, rule_id %s, name %s", c->target_worker, c->rule_id, c->trigger_name); dump_trigger(&trigger_memory); triggerfunction trigger_func; if(!(trigger_func = find_trigger(c->channel, c->trigger_name))) { zclock_log("no trigger found for channel %s, trigger %s", c->channel, c->trigger_name); send_sync("no such trigger", control); return; } void * line = zsocket_new(context, ZMQ_SUB); // what line are we on? // this comes in the addins. char * linesocket = to_linesocket(trigger_memory.line_id); zclock_log("trigger is connecting to listen on %s", linesocket); zsocket_connect(line, linesocket); zsockopt_set_unsubscribe(line, ""); zsockopt_set_subscribe(line, "VALUE"); recv_sync("ping", control); send_sync("pong", control); zmq_pollitem_t items [] = { { line, 0, ZMQ_POLLIN, 0 }, { control, 0, ZMQ_POLLIN, 0 } }; while(1) { // listen on control and line zmq_poll (items, 2, -1); if (items[1].revents & ZMQ_POLLIN) { zclock_log("rule %s received message on control pipe", c->rule_id); // control message // really only expecting DESTROY zmsg_t * msg = zmsg_recv(control); char * str = zmsg_popstr(msg); zmsg_destroy(&msg); if (strcmp("Destroy", str) == 0) { zclock_log("rule %s will quit on request", c->rule_id); free(str); send_sync("ok", control); zclock_log("rule %s quitting on request", c->rule_id); break; } else { zclock_log("unexpected command %s for rule %s", str, c->rule_id); free(str); send_sync("ok", control); } } if (items[0].revents & ZMQ_POLLIN) { // serial update zmsg_t * msg = zmsg_recv(line); zframe_t * cmd = zmsg_pop(msg); if(zframe_streq(cmd, "CHANNEL_CHANGE")) { // TODO // must have been dormant to have gotten this char * new_channel = zmsg_popstr(msg); if(strcmp(c->channel, new_channel) == 0) { // oh, happy day! We're relevant again. // reactivate and start looking at reset levels. zclock_log("line %d: changed channel from %s to %s: trigger coming back to life", trigger_memory.line_id, c->channel, new_channel); zsockopt_set_subscribe(line, "VALUE"); zsockopt_set_unsubscribe(line, "CHANNEL_CHANGE"); } free(new_channel); } else if (zframe_streq(cmd, "VALUE")) { zframe_t * vframe = zmsg_pop(msg); int value; memcpy(&value, zframe_data(vframe), sizeof(int)); char * update_channel = zmsg_popstr(msg); if(strcmp(c->channel, update_channel) != 0) { // channel changed, go dormant // this is legit according to my tests at // https://gist.github.com/2042350 zclock_log("line %d: changed channel from %s to %s: trigger going dormant", trigger_memory.line_id, c->channel, update_channel); zsockopt_set_subscribe(line, "CHANNEL_CHANGE"); zsockopt_set_unsubscribe(line, "VALUE"); } else if(trigger_func(&trigger_memory, value)) { send_trigger(client, c->target_worker, c->rule_id, value, user_id); } free(update_channel); } else { // shouldn't ever happen. zclock_log("shouldn't have received command %s\n", zframe_strdup(cmd)); } zmsg_destroy(&msg); zframe_destroy(&cmd); } } msgpack_zone_destroy(&mempool); }