@@ -293,9 +293,6 @@ bool Element::IsObscured(LocationInfo* click_location,
293
293
return false ;
294
294
}
295
295
296
- CComPtr<IHTMLDocument2> doc;
297
- this ->GetContainingDocument (false , &doc);
298
-
299
296
// If an element has a style value where pointer-events is set to 'none',
300
297
// the element is "obscured" by definition, since any mouse interaction
301
298
// will not be handled by the element.
@@ -308,64 +305,49 @@ bool Element::IsObscured(LocationInfo* click_location,
308
305
}
309
306
}
310
307
311
- bool is_obscured = false ;
312
-
313
- std::vector<LocationInfo> frame_locations;
308
+ // The element being obscured only makes sense within the context
309
+ // of its own document, even if it's not in the top-level document.
314
310
LocationInfo element_location = {};
315
- int status_code = this ->GetLocation (&element_location, &frame_locations);
316
- bool document_contains_frames = frame_locations.size () != 0 ;
317
- *click_location = this ->CalculateClickPoint (element_location,
318
- document_contains_frames);
311
+ int status_code = this ->GetLocation (&element_location, nullptr );
312
+ *click_location = this ->CalculateClickPoint (element_location, false );
319
313
long x = click_location->x ;
320
314
long y = click_location->y ;
321
- if (document_contains_frames) {
322
- // If the document contains frames, we'll need to do elementsFromPoint
323
- // for the framed document, ignoring the frame offsets.
324
- CComPtr<IHTMLElement2> rect_element;
325
- this ->element_ ->QueryInterface <IHTMLElement2>(&rect_element);
326
- CComPtr<IHTMLRect> rect;
327
- rect_element->getBoundingClientRect (&rect);
328
- long top = 0 , bottom = 0 , left = 0 , right = 0 ;
329
-
330
- rect->get_top (&top);
331
- rect->get_left (&left);
332
- rect->get_bottom (&bottom);
333
- rect->get_right (&right);
334
315
335
- long width = right - left;
336
- long height = bottom - top;
337
-
338
- x = left + (width / 2 );
339
- y = top + (height / 2 );
340
- }
316
+ bool is_inline = this ->IsInline ();
341
317
318
+ CComPtr<IHTMLDocument2> doc;
319
+ this ->GetContainingDocument (false , &doc);
342
320
CComPtr<IHTMLElement> element_hit;
343
321
hr = doc->elementFromPoint (x, y, &element_hit);
344
- if (SUCCEEDED (hr) && element_.IsEqualObject (element_hit)) {
345
- // Short circuit the use of elementsFromPoint if we don't
346
- // have to use it.
347
- return false ;
348
- } else {
349
- // Short circuit in the case where this element is specifically
350
- // a <label> element, and the top-most element as determined by
351
- // elementFromPoint is a direct child of this element. This is
352
- // to work around IE's bug in elementsFromPoint that does not
353
- // return <label> elements in the list of elements hit.
354
- // N.B., this is a hack of the highest order, and there's every
355
- // likelihood that some page somewhere will fail this check.
356
- CComPtr<IHTMLLabelElement> label;
357
- hr = this ->element_ ->QueryInterface <IHTMLLabelElement>(&label);
358
- if (SUCCEEDED (hr) && label) {
359
- CComPtr<IHTMLElement> list_element_parent;
360
- hr = element_hit->get_parentElement (&list_element_parent);
361
- if (SUCCEEDED (hr) && list_element_parent) {
362
- if (this ->element_ .IsEqualObject (list_element_parent)) {
363
- return false ;
322
+ if (SUCCEEDED (hr) && element_hit) {
323
+ if (element_.IsEqualObject (element_hit)) {
324
+ // Short circuit the use of elementsFromPoint if we don't
325
+ // have to use it.
326
+ return false ;
327
+ } else {
328
+ // Short circuit in the case where this element is specifically
329
+ // an "inline" element (<label>, <span>, <a>, at present),
330
+ // and the top-most element as determined by elementFromPoint is
331
+ // a direct child of this element. This is to work around IE's bug
332
+ // in elementsFromPoint that does not return inline elements in the
333
+ // list of elements hit.
334
+ // N.B., this is a hack of the highest order, and there's every
335
+ // likelihood that some page somewhere will fail this check.
336
+ if (is_inline) {
337
+ CComPtr<IHTMLElement> element_hit_parent;
338
+ hr = element_hit->get_parentElement (&element_hit_parent);
339
+ CComBSTR element_hit_parent_tag;
340
+ element_hit_parent->get_tagName (&element_hit_parent_tag);
341
+ if (SUCCEEDED (hr) && element_hit_parent) {
342
+ if (this ->element_ .IsEqualObject (element_hit_parent)) {
343
+ return false ;
344
+ }
364
345
}
365
346
}
366
347
}
367
348
}
368
349
350
+ bool is_obscured = false ;
369
351
CComPtr<IHTMLDocument8> elements_doc;
370
352
hr = doc.QueryInterface <IHTMLDocument8>(&elements_doc);
371
353
if (FAILED (hr)) {
@@ -419,37 +401,33 @@ bool Element::IsObscured(LocationInfo* click_location,
419
401
420
402
CComPtr<IHTMLCSSStyleDeclaration> list_element_computed_style;
421
403
if (list_element_wrapper.GetComputedStyle (&list_element_computed_style)) {
422
- // If the element has a pointer-events value set to 'none', it
423
- // may be technically obscuring this element, but manipulating
424
- // it with the pointer device has no effect, so it is effectively
425
- // not obscuring this element.
426
404
CComBSTR list_element_pointer_events_value = L" " ;
427
405
hr = list_element_computed_style->get_pointerEvents (&list_element_pointer_events_value);
428
- if (SUCCEEDED (hr) && list_element_pointer_events_value == L" none" ) {
429
- continue ;
430
- } else {
431
- CComVariant opacity_variant;
432
- hr = list_element_computed_style->get_opacity (&opacity_variant);
433
- if (SUCCEEDED (hr)) {
434
- double opacity_value = 1.0 ;
435
- if (opacity_variant.vt == VT_BSTR) {
436
- opacity_value = _wtof (opacity_variant.bstrVal );
437
- } else {
438
- opacity_value = opacity_variant.dblVal ;
439
- }
440
-
441
- // If the element has an opacity less than 1.0, it's in a
442
- // different stacking context, and will be drawn below the
443
- // element we want to interact with.
444
- if (opacity_value >= 1.0 ) {
445
- is_obscured = true ;
446
- }
447
- }
406
+ if (SUCCEEDED (hr) && list_element_pointer_events_value != L" none" ) {
407
+ // If the element has a pointer-events value set to 'none', it
408
+ // may be technically obscuring this element, but manipulating
409
+ // it with the pointer device has no effect, so it is effectively
410
+ // not obscuring this element.
411
+ is_obscured = true ;
412
+ break ;
448
413
}
449
414
} else {
450
415
// We were unable to retrieve the computed style, so we must assume
451
416
// the other element is obscuring this one.
452
417
is_obscured = true ;
418
+ break ;
419
+ }
420
+ } else {
421
+ // Repeating the immediate-child-of-inline-element hack from above for
422
+ // elements found in the list.
423
+ if (is_inline) {
424
+ CComPtr<IHTMLElement> list_element_parent;
425
+ hr = element_in_list->get_parentElement (&list_element_parent);
426
+ if (SUCCEEDED (hr) && list_element_parent) {
427
+ if (this ->element_ .IsEqualObject (list_element_parent)) {
428
+ break ;
429
+ }
430
+ }
453
431
}
454
432
}
455
433
if (is_obscured) {
@@ -809,10 +787,11 @@ bool Element::IsSelected() {
809
787
return selected;
810
788
}
811
789
812
- int Element::GetLocation (LocationInfo* location, std::vector<LocationInfo>* frame_locations) {
790
+ int Element::GetLocation (LocationInfo* location,
791
+ std::vector<LocationInfo>* frame_locations) {
813
792
LOG (TRACE) << " Entering Element::GetLocation" ;
814
793
815
- bool hasAbsolutePositionReadyToReturn = false ;
794
+ bool has_absolute_position_ready_to_return = false ;
816
795
817
796
CComPtr<IHTMLElement2> element2;
818
797
HRESULT hr = this ->element_ ->QueryInterface (&element2);
@@ -845,7 +824,7 @@ int Element::GetLocation(LocationInfo* location, std::vector<LocationInfo>* fram
845
824
if (RectHasNonZeroDimensions (rect)) {
846
825
// IE returns absolute positions in the page, rather than frame- and scroll-bound
847
826
// positions, for clientRects (as opposed to boundingClientRects).
848
- hasAbsolutePositionReadyToReturn = true ;
827
+ has_absolute_position_ready_to_return = true ;
849
828
break ;
850
829
}
851
830
}
@@ -887,17 +866,22 @@ int Element::GetLocation(LocationInfo* location, std::vector<LocationInfo>* fram
887
866
CComPtr<IHTMLDOMChildrenCollection> children;
888
867
children_dispatch->QueryInterface <IHTMLDOMChildrenCollection>(&children);
889
868
if (!!children) {
890
- long childrenCount = 0 ;
891
- children->get_length (&childrenCount );
892
- for (long i = 0 ; i < childrenCount ; ++i) {
893
- CComPtr<IDispatch> childDispatch ;
894
- children->item (i, &childDispatch );
869
+ long children_count = 0 ;
870
+ children->get_length (&children_count );
871
+ for (long i = 0 ; i < children_count ; ++i) {
872
+ CComPtr<IDispatch> child_dispatch ;
873
+ children->item (i, &child_dispatch );
895
874
CComPtr<IHTMLElement> child;
896
- childDispatch ->QueryInterface (&child);
875
+ child_dispatch ->QueryInterface (&child);
897
876
if (child != NULL ) {
898
- Element childElement (child, this ->containing_window_handle_ );
899
- std::vector<LocationInfo> child_frame_locations;
900
- int result = childElement.GetLocation (location, &child_frame_locations);
877
+ int result = WD_SUCCESS;
878
+ Element child_element (child, this ->containing_window_handle_ );
879
+ if (frame_locations == nullptr ) {
880
+ result = child_element.GetLocation (location, nullptr );
881
+ } else {
882
+ std::vector<LocationInfo> child_frame_locations;
883
+ result = child_element.GetLocation (location, &child_frame_locations);
884
+ }
901
885
if (result == WD_SUCCESS) {
902
886
return result;
903
887
}
@@ -917,7 +901,7 @@ int Element::GetLocation(LocationInfo* location, std::vector<LocationInfo>* fram
917
901
long h = bottom - top;
918
902
919
903
bool element_is_in_frame = this ->AppendFrameDetails (frame_locations);
920
- if (!hasAbsolutePositionReadyToReturn ) {
904
+ if (!has_absolute_position_ready_to_return ) {
921
905
// On versions of IE prior to 8 on Vista, if the element is out of the
922
906
// viewport this would seem to return 0,0,0,0. IE 8 returns position in
923
907
// the DOM regardless of whether it's in the browser viewport.
@@ -991,6 +975,10 @@ bool Element::RectHasNonZeroDimensions(IHTMLRect* rect) {
991
975
bool Element::AppendFrameDetails (std::vector<LocationInfo>* frame_locations) {
992
976
LOG (TRACE) << " Entering Element::GetFrameDetails" ;
993
977
978
+ if (frame_locations == nullptr ) {
979
+ return false ;
980
+ }
981
+
994
982
CComPtr<IHTMLDocument2> owner_doc;
995
983
int status_code = this ->GetContainingDocument (true , &owner_doc);
996
984
if (status_code != WD_SUCCESS) {
0 commit comments