I know this is old, but I had the same question. I finally figured it out. You include an expression in braces and simply list the events / reactive objects. My (unsubstantiated) guess is that shiny simply performs the same reactive pointer analysis to this expression block as to a standard reactive
block.
observeEvent({
input$spec_button
mainplot.click$click
1
}, { ... } )
EDIT
Updated to handle the case where the last line in the expression returns NULL. Simply return a constant value.