func (e *Element) AttachHandler(handler *EventHandler) { attachedHandlers, hasAttachments := eventHandlers[e.handle] if hasAttachments { if _, exists := attachedHandlers[handler]; exists { // This exact event handler is already attached to this exact element. return } } // Don't let the caller disable ATTACH/DETACH events, otherwise we // won't know when to throw out our event handler object subscription := handler.Subscription() subscription &= ^uint32(DISABLE_INITIALIZATION & 0xffffffff) tag := uintptr(unsafe.Pointer(handler)) if subscription == HANDLE_ALL { if ret := C.HTMLayoutAttachEventHandler(e.handle, (*[0]byte)(unsafe.Pointer(goElementProc)), C.LPVOID(tag)); ret != HLDOM_OK { domPanic(ret, "Failed to attach event handler to element") } } else { if ret := C.HTMLayoutAttachEventHandlerEx(e.handle, (*[0]byte)(unsafe.Pointer(goElementProc)), C.LPVOID(tag), C.UINT(subscription)); ret != HLDOM_OK { domPanic(ret, "Failed to attach event handler to element") } } if !hasAttachments { eventHandlers[e.handle] = make(map[*EventHandler]bool, 8) } eventHandlers[e.handle][handler] = true }
// This is the same as AttachHandler, except that behaviors are singleton instances stored // in a master map. They may be shared among many elements since they have no state. // The only reason we keep a separate set of the behaviors is so that the event handler // dispatch method can tell if an event handler is a behavior or a regular handler. func (e *Element) attachBehavior(handler *EventHandler) { tag := uintptr(unsafe.Pointer(handler)) if subscription := handler.Subscription(); subscription == HANDLE_ALL { if ret := C.HTMLayoutAttachEventHandler(e.handle, (*[0]byte)(unsafe.Pointer(goElementProc)), C.LPVOID(tag)); ret != HLDOM_OK { domPanic(ret, "Failed to attach event handler to element") } } else { if ret := C.HTMLayoutAttachEventHandlerEx(e.handle, (*[0]byte)(unsafe.Pointer(goElementProc)), C.LPVOID(tag), C.UINT(subscription)); ret != HLDOM_OK { domPanic(ret, "Failed to attach event handler to element") } } }