Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygennsevents.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2007-2008 Jacek Caban for CodeWeavers 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 */ 00018 00019 #include "config.h" 00020 00021 #include <stdarg.h> 00022 00023 #define COBJMACROS 00024 00025 #include "windef.h" 00026 #include "winbase.h" 00027 #include "winuser.h" 00028 #include "ole2.h" 00029 #include "mshtmcid.h" 00030 #include "shlguid.h" 00031 00032 #include "wine/debug.h" 00033 #include "wine/unicode.h" 00034 00035 #include "mshtml_private.h" 00036 #include "htmlevent.h" 00037 00038 WINE_DEFAULT_DEBUG_CHANNEL(mshtml); 00039 00040 typedef struct { 00041 const nsIDOMEventListenerVtbl *lpDOMEventListenerVtbl; 00042 nsDocumentEventListener *This; 00043 } nsEventListener; 00044 00045 struct nsDocumentEventListener { 00046 nsEventListener blur_listener; 00047 nsEventListener focus_listener; 00048 nsEventListener keypress_listener; 00049 nsEventListener load_listener; 00050 nsEventListener htmlevent_listener; 00051 00052 LONG ref; 00053 00054 HTMLDocumentNode *doc; 00055 }; 00056 00057 static LONG release_listener(nsDocumentEventListener *This) 00058 { 00059 LONG ref = InterlockedDecrement(&This->ref); 00060 00061 TRACE("(%p) ref=%d\n", This, ref); 00062 00063 if(!ref) 00064 heap_free(This); 00065 00066 return ref; 00067 } 00068 00069 #define NSEVENTLIST_THIS(iface) DEFINE_THIS(nsEventListener, DOMEventListener, iface) 00070 00071 static nsresult NSAPI nsDOMEventListener_QueryInterface(nsIDOMEventListener *iface, 00072 nsIIDRef riid, nsQIResult result) 00073 { 00074 nsEventListener *This = NSEVENTLIST_THIS(iface); 00075 00076 *result = NULL; 00077 00078 if(IsEqualGUID(&IID_nsISupports, riid)) { 00079 TRACE("(%p)->(IID_nsISupports, %p)\n", This, result); 00080 *result = NSEVENTLIST(This); 00081 }else if(IsEqualGUID(&IID_nsIDOMEventListener, riid)) { 00082 TRACE("(%p)->(IID_nsIDOMEventListener %p)\n", This, result); 00083 *result = NSEVENTLIST(This); 00084 } 00085 00086 if(*result) { 00087 nsIWebBrowserChrome_AddRef(NSEVENTLIST(This)); 00088 return NS_OK; 00089 } 00090 00091 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result); 00092 return NS_NOINTERFACE; 00093 } 00094 00095 static nsrefcnt NSAPI nsDOMEventListener_AddRef(nsIDOMEventListener *iface) 00096 { 00097 nsDocumentEventListener *This = NSEVENTLIST_THIS(iface)->This; 00098 LONG ref = InterlockedIncrement(&This->ref); 00099 00100 TRACE("(%p) ref=%d\n", This, ref); 00101 00102 return ref; 00103 } 00104 00105 static nsrefcnt NSAPI nsDOMEventListener_Release(nsIDOMEventListener *iface) 00106 { 00107 nsDocumentEventListener *This = NSEVENTLIST_THIS(iface)->This; 00108 00109 return release_listener(This); 00110 } 00111 00112 static BOOL is_doc_child_focus(NSContainer *nscontainer) 00113 { 00114 HWND hwnd; 00115 00116 for(hwnd = GetFocus(); hwnd && hwnd != nscontainer->hwnd; hwnd = GetParent(hwnd)); 00117 00118 return hwnd != NULL; 00119 } 00120 00121 static nsresult NSAPI handle_blur(nsIDOMEventListener *iface, nsIDOMEvent *event) 00122 { 00123 HTMLDocumentNode *doc = NSEVENTLIST_THIS(iface)->This->doc; 00124 HTMLDocumentObj *doc_obj; 00125 00126 TRACE("(%p)\n", doc); 00127 00128 if(!doc || !doc->basedoc.doc_obj) 00129 return NS_ERROR_FAILURE; 00130 doc_obj = doc->basedoc.doc_obj; 00131 00132 if(doc_obj->focus && !is_doc_child_focus(doc_obj->nscontainer)) { 00133 doc_obj->focus = FALSE; 00134 notif_focus(doc_obj); 00135 } 00136 00137 return NS_OK; 00138 } 00139 00140 static nsresult NSAPI handle_focus(nsIDOMEventListener *iface, nsIDOMEvent *event) 00141 { 00142 HTMLDocumentNode *doc = NSEVENTLIST_THIS(iface)->This->doc; 00143 HTMLDocumentObj *doc_obj; 00144 00145 TRACE("(%p)\n", doc); 00146 00147 if(!doc) 00148 return NS_ERROR_FAILURE; 00149 doc_obj = doc->basedoc.doc_obj; 00150 00151 if(!doc_obj->focus) { 00152 doc_obj->focus = TRUE; 00153 notif_focus(doc_obj); 00154 } 00155 00156 return NS_OK; 00157 } 00158 00159 static nsresult NSAPI handle_keypress(nsIDOMEventListener *iface, 00160 nsIDOMEvent *event) 00161 { 00162 HTMLDocumentNode *doc = NSEVENTLIST_THIS(iface)->This->doc; 00163 HTMLDocumentObj *doc_obj; 00164 00165 if(!doc) 00166 return NS_ERROR_FAILURE; 00167 doc_obj = doc->basedoc.doc_obj; 00168 00169 TRACE("(%p)->(%p)\n", doc, event); 00170 00171 update_doc(&doc_obj->basedoc, UPDATE_UI); 00172 if(doc_obj->usermode == EDITMODE) 00173 handle_edit_event(&doc_obj->basedoc, event); 00174 00175 return NS_OK; 00176 } 00177 00178 static void handle_docobj_load(HTMLDocumentObj *doc) 00179 { 00180 IOleCommandTarget *olecmd = NULL; 00181 HRESULT hres; 00182 00183 if(!doc->client) 00184 return; 00185 00186 hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&olecmd); 00187 if(SUCCEEDED(hres)) { 00188 if(doc->download_state) { 00189 VARIANT state, progress; 00190 00191 V_VT(&progress) = VT_I4; 00192 V_I4(&progress) = 0; 00193 IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_SETPROGRESSPOS, 00194 OLECMDEXECOPT_DONTPROMPTUSER, &progress, NULL); 00195 00196 V_VT(&state) = VT_I4; 00197 V_I4(&state) = 0; 00198 IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_SETDOWNLOADSTATE, 00199 OLECMDEXECOPT_DONTPROMPTUSER, &state, NULL); 00200 } 00201 00202 IOleCommandTarget_Exec(olecmd, &CGID_ShellDocView, 103, 0, NULL, NULL); 00203 IOleCommandTarget_Exec(olecmd, &CGID_MSHTML, IDM_PARSECOMPLETE, 0, NULL, NULL); 00204 IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_HTTPEQUIV_DONE, 0, NULL, NULL); 00205 00206 IOleCommandTarget_Release(olecmd); 00207 } 00208 doc->download_state = 0; 00209 } 00210 00211 static nsresult NSAPI handle_load(nsIDOMEventListener *iface, nsIDOMEvent *event) 00212 { 00213 HTMLDocumentNode *doc = NSEVENTLIST_THIS(iface)->This->doc; 00214 HTMLDocumentObj *doc_obj; 00215 nsIDOMHTMLElement *nsbody = NULL; 00216 00217 TRACE("(%p)\n", doc); 00218 00219 if(!doc || !doc->basedoc.window) 00220 return NS_ERROR_FAILURE; 00221 doc_obj = doc->basedoc.doc_obj; 00222 00223 connect_scripts(doc->basedoc.window); 00224 00225 if(doc_obj->nscontainer->editor_controller) { 00226 nsIController_Release(doc_obj->nscontainer->editor_controller); 00227 doc_obj->nscontainer->editor_controller = NULL; 00228 } 00229 00230 if(doc_obj->usermode == EDITMODE) 00231 handle_edit_load(&doc_obj->basedoc); 00232 00233 if(doc == doc_obj->basedoc.doc_node) 00234 handle_docobj_load(doc_obj); 00235 00236 set_ready_state(doc->basedoc.window, READYSTATE_COMPLETE); 00237 00238 if(doc == doc_obj->basedoc.doc_node) { 00239 if(doc_obj->view_sink) 00240 IAdviseSink_OnViewChange(doc_obj->view_sink, DVASPECT_CONTENT, -1); 00241 00242 if(doc_obj->frame) { 00243 static const WCHAR wszDone[] = {'D','o','n','e',0}; 00244 IOleInPlaceFrame_SetStatusText(doc_obj->frame, wszDone); 00245 } 00246 00247 update_title(doc_obj); 00248 } 00249 00250 if(!doc->nsdoc) { 00251 ERR("NULL nsdoc\n"); 00252 return NS_ERROR_FAILURE; 00253 } 00254 00255 nsIDOMHTMLDocument_GetBody(doc->nsdoc, &nsbody); 00256 if(nsbody) { 00257 fire_event(doc, EVENTID_LOAD, TRUE, (nsIDOMNode*)nsbody, event); 00258 nsIDOMHTMLElement_Release(nsbody); 00259 } 00260 00261 return NS_OK; 00262 } 00263 00264 static nsresult NSAPI handle_htmlevent(nsIDOMEventListener *iface, nsIDOMEvent *event) 00265 { 00266 HTMLDocumentNode *doc = NSEVENTLIST_THIS(iface)->This->doc; 00267 const PRUnichar *type; 00268 nsIDOMEventTarget *event_target; 00269 nsIDOMNode *nsnode; 00270 nsAString type_str; 00271 eventid_t eid; 00272 nsresult nsres; 00273 00274 TRACE("\n"); 00275 00276 nsAString_Init(&type_str, NULL); 00277 nsIDOMEvent_GetType(event, &type_str); 00278 nsAString_GetData(&type_str, &type); 00279 eid = str_to_eid(type); 00280 nsAString_Finish(&type_str); 00281 00282 nsres = nsIDOMEvent_GetTarget(event, &event_target); 00283 if(NS_FAILED(nsres) || !event_target) { 00284 ERR("GetEventTarget failed: %08x\n", nsres); 00285 return NS_OK; 00286 } 00287 00288 nsres = nsIDOMEventTarget_QueryInterface(event_target, &IID_nsIDOMNode, (void**)&nsnode); 00289 nsIDOMEventTarget_Release(event_target); 00290 if(NS_FAILED(nsres)) { 00291 ERR("Could not get nsIDOMNode: %08x\n", nsres); 00292 return NS_OK; 00293 } 00294 00295 fire_event(doc, eid, TRUE, nsnode, event); 00296 00297 nsIDOMNode_Release(nsnode); 00298 00299 return NS_OK; 00300 } 00301 00302 #undef NSEVENTLIST_THIS 00303 00304 #define EVENTLISTENER_VTBL(handler) \ 00305 { \ 00306 nsDOMEventListener_QueryInterface, \ 00307 nsDOMEventListener_AddRef, \ 00308 nsDOMEventListener_Release, \ 00309 handler, \ 00310 } 00311 00312 static const nsIDOMEventListenerVtbl blur_vtbl = EVENTLISTENER_VTBL(handle_blur); 00313 static const nsIDOMEventListenerVtbl focus_vtbl = EVENTLISTENER_VTBL(handle_focus); 00314 static const nsIDOMEventListenerVtbl keypress_vtbl = EVENTLISTENER_VTBL(handle_keypress); 00315 static const nsIDOMEventListenerVtbl load_vtbl = EVENTLISTENER_VTBL(handle_load); 00316 static const nsIDOMEventListenerVtbl htmlevent_vtbl = EVENTLISTENER_VTBL(handle_htmlevent); 00317 00318 static void init_event(nsIDOMEventTarget *target, const PRUnichar *type, 00319 nsIDOMEventListener *listener, BOOL capture) 00320 { 00321 nsAString type_str; 00322 nsresult nsres; 00323 00324 nsAString_InitDepend(&type_str, type); 00325 nsres = nsIDOMEventTarget_AddEventListener(target, &type_str, listener, capture); 00326 nsAString_Finish(&type_str); 00327 if(NS_FAILED(nsres)) 00328 ERR("AddEventTarget failed: %08x\n", nsres); 00329 00330 } 00331 00332 static void init_listener(nsEventListener *This, nsDocumentEventListener *listener, 00333 const nsIDOMEventListenerVtbl *vtbl) 00334 { 00335 This->lpDOMEventListenerVtbl = vtbl; 00336 This->This = listener; 00337 } 00338 00339 void add_nsevent_listener(HTMLDocumentNode *doc, nsIDOMNode *nsnode, LPCWSTR type) 00340 { 00341 nsIDOMEventTarget *target; 00342 nsresult nsres; 00343 00344 if(nsnode) 00345 nsres = nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMEventTarget, (void**)&target); 00346 else 00347 nsres = nsIDOMWindow_QueryInterface(doc->basedoc.window->nswindow, &IID_nsIDOMEventTarget, (void**)&target); 00348 if(NS_FAILED(nsres)) { 00349 ERR("Could not get nsIDOMEventTarget interface: %08x\n", nsres); 00350 return; 00351 } 00352 00353 init_event(target, type, NSEVENTLIST(&doc->nsevent_listener->htmlevent_listener), TRUE); 00354 nsIDOMEventTarget_Release(target); 00355 } 00356 00357 void release_nsevents(HTMLDocumentNode *doc) 00358 { 00359 if(doc->nsevent_listener) { 00360 doc->nsevent_listener->doc = NULL; 00361 release_listener(doc->nsevent_listener); 00362 doc->nsevent_listener = NULL; 00363 } 00364 } 00365 00366 void init_nsevents(HTMLDocumentNode *doc) 00367 { 00368 nsDocumentEventListener *listener; 00369 nsIDOMEventTarget *target; 00370 nsresult nsres; 00371 00372 static const PRUnichar wsz_blur[] = {'b','l','u','r',0}; 00373 static const PRUnichar wsz_focus[] = {'f','o','c','u','s',0}; 00374 static const PRUnichar wsz_keypress[] = {'k','e','y','p','r','e','s','s',0}; 00375 static const PRUnichar wsz_load[] = {'l','o','a','d',0}; 00376 00377 listener = heap_alloc(sizeof(nsDocumentEventListener)); 00378 if(!listener) 00379 return; 00380 00381 listener->ref = 1; 00382 listener->doc = doc; 00383 00384 init_listener(&listener->blur_listener, listener, &blur_vtbl); 00385 init_listener(&listener->focus_listener, listener, &focus_vtbl); 00386 init_listener(&listener->keypress_listener, listener, &keypress_vtbl); 00387 init_listener(&listener->load_listener, listener, &load_vtbl); 00388 init_listener(&listener->htmlevent_listener, listener, &htmlevent_vtbl); 00389 00390 doc->nsevent_listener = listener; 00391 00392 nsres = nsIDOMWindow_QueryInterface(doc->basedoc.window->nswindow, &IID_nsIDOMEventTarget, (void**)&target); 00393 if(NS_FAILED(nsres)) { 00394 ERR("Could not get nsIDOMEventTarget interface: %08x\n", nsres); 00395 return; 00396 } 00397 00398 init_event(target, wsz_blur, NSEVENTLIST(&listener->blur_listener), TRUE); 00399 init_event(target, wsz_focus, NSEVENTLIST(&listener->focus_listener), TRUE); 00400 init_event(target, wsz_keypress, NSEVENTLIST(&listener->keypress_listener), FALSE); 00401 init_event(target, wsz_load, NSEVENTLIST(&listener->load_listener), TRUE); 00402 00403 nsIDOMEventTarget_Release(target); 00404 } Generated on Sun May 27 2012 04:25:03 for ReactOS by
1.7.6.1
|