Skip to content

Commit abfb96f

Browse files
committed
Updating IE to prep for refactor of element click point calculation
1 parent d9bea90 commit abfb96f

File tree

2 files changed

+104
-2
lines changed

2 files changed

+104
-2
lines changed

cpp/iedriver/Element.cpp

Lines changed: 102 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,16 @@ int Element::GetLocationOnceScrolledIntoView(const ElementScrollBehavior scroll,
740740
LOG(WARN) << "Scrolled element is not in view";
741741
status_code = EELEMENTCLICKPOINTNOTSCROLLED;
742742
}
743+
744+
// TODO: Handle the case where the element's click point is in
745+
// the view port but hidden by the overflow of a parent element.
746+
// That could would look something like the following:
747+
// if (this->IsHiddenByOverflow(element_location, click_location)) {
748+
// if (!this->IsEntirelyHiddenByOverflow()) {
749+
// this->ScrollWithinOverflow(element_location);
750+
// }
751+
// status_code = EELEMENTCLICKPOINTNOTSCROLLED;
752+
// }
743753
}
744754

745755
LOG(DEBUG) << "(x, y, w, h): "
@@ -793,6 +803,83 @@ bool Element::IsHiddenByOverflow(const LocationInfo element_location,
793803
return is_overflow;
794804
}
795805

806+
bool Element::IsEntirelyHiddenByOverflow() {
807+
LOG(TRACE) << "Entering Element::IsEntirelyHiddenByOverflow";
808+
809+
bool is_overflow = false;
810+
811+
std::wstring script_source(L"(function() { return (");
812+
script_source += atoms::asString(atoms::IS_ELEMENT_IN_PARENT_OVERFLOW);
813+
script_source += L")})();";
814+
815+
CComPtr<IHTMLDocument2> doc;
816+
this->GetContainingDocument(false, &doc);
817+
Script script_wrapper(doc, script_source, 1);
818+
script_wrapper.AddArgument(this->element_);
819+
int status_code = script_wrapper.Execute();
820+
if (status_code == WD_SUCCESS) {
821+
std::wstring raw_overflow_state(script_wrapper.result().bstrVal);
822+
std::string overflow_state = StringUtilities::ToString(raw_overflow_state);
823+
is_overflow = (overflow_state == "scroll");
824+
} else {
825+
LOG(WARN) << "Unable to determine is element hidden by overflow";
826+
}
827+
828+
return is_overflow;
829+
}
830+
831+
bool Element::ScrollWithinOverflow(const LocationInfo element_location) {
832+
RECT element_rect;
833+
element_rect.left = element_location.x;
834+
element_rect.top = element_location.y;
835+
element_rect.right = element_location.x + element_location.width;
836+
element_rect.bottom = element_location.y + element_location.height;
837+
838+
CComPtr<IHTMLElement> parent_element;
839+
this->element_->get_parentElement(&parent_element);
840+
while (parent_element != NULL) {
841+
CComPtr<IHTMLElement2> el2;
842+
parent_element->QueryInterface<IHTMLElement2>(&el2);
843+
CComPtr<IHTMLRect> parent_bounding_rect;
844+
el2->getBoundingClientRect(&parent_bounding_rect);
845+
RECT parent_rect;
846+
parent_bounding_rect->get_left(&parent_rect.left);
847+
parent_bounding_rect->get_top(&parent_rect.top);
848+
parent_bounding_rect->get_right(&parent_rect.right);
849+
parent_bounding_rect->get_bottom(&parent_rect.bottom);
850+
RECT intersection;
851+
if (::IntersectRect(&intersection, &element_rect, &parent_rect)) {
852+
if (::EqualRect(&intersection, &element_rect)) {
853+
CComPtr<IHTMLElement> next_ancestor;
854+
// The entire element is visible within this ancestor.
855+
// Need to proceed to the next ancestor in the tree.
856+
parent_element->get_parentElement(&next_ancestor);
857+
parent_element.Release();
858+
parent_element = next_ancestor;
859+
} else {
860+
// We have the intersecting rect, so adjust the location
861+
long intersection_vert_center = intersection.top + ((intersection.bottom - intersection.top) / 2);
862+
long intersection_horiz_center = intersection.left + ((intersection.right - intersection.left) / 2);
863+
864+
long offset_top = 0;
865+
element_->get_offsetTop(&offset_top);
866+
offset_top += element_location.height / 2;
867+
868+
long offset_left = 0;
869+
element_->get_offsetLeft(&offset_left);
870+
offset_left += element_location.width / 2;
871+
872+
el2->put_scrollTop(offset_top - intersection_vert_center);
873+
el2->put_scrollLeft(offset_left - intersection_horiz_center);
874+
return true;
875+
}
876+
} else {
877+
// the rects don't intersect, so something went wrong.
878+
break;
879+
}
880+
}
881+
return false;
882+
}
796883
bool Element::IsLocationVisibleInFrames(const LocationInfo location,
797884
const std::vector<LocationInfo> frame_locations) {
798885
std::vector<LocationInfo>::const_iterator iterator = frame_locations.begin();
@@ -1417,7 +1504,20 @@ LocationInfo Element::CalculateClickPoint(const LocationInfo location, const boo
14171504
LocationInfo clickable_viewport = {};
14181505
bool result = this->GetClickableViewPortLocation(document_contains_frames,
14191506
&clickable_viewport);
1507+
14201508
if (result) {
1509+
// TODO: Handle the case where the center of the target element
1510+
// is already in the view port. The code would look something like
1511+
// the following:
1512+
// If the center of the target element is already in the view port,
1513+
// we don't need to adjust to find the "in view center point."
1514+
// Technically, this is a deliberate violation of the spec.
1515+
//long element_center_x = location.x + static_cast<long>(floor(location.width / 2.0));
1516+
//long element_center_y = location.y + static_cast<long>(floor(location.height / 2.0));
1517+
//if (element_center_x < 0 ||
1518+
// element_center_x >= clickable_viewport.width ||
1519+
// element_center_y < 0 ||
1520+
// element_center_y >= clickable_viewport.height) {
14211521
RECT element_rect;
14221522
element_rect.left = location.x;
14231523
element_rect.top = location.y;
@@ -1432,8 +1532,8 @@ LocationInfo Element::CalculateClickPoint(const LocationInfo location, const boo
14321532

14331533
RECT intersect_rect;
14341534
BOOL is_intersecting = ::IntersectRect(&intersect_rect,
1435-
&element_rect,
1436-
&viewport_rect);
1535+
&element_rect,
1536+
&viewport_rect);
14371537
if (is_intersecting) {
14381538
corrected_width = intersect_rect.right - intersect_rect.left;
14391539
corrected_height = intersect_rect.bottom - intersect_rect.top;

cpp/iedriver/Element.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ class Element {
8989
const std::vector<LocationInfo> frame_locations);
9090
bool IsHiddenByOverflow(const LocationInfo element_location,
9191
const LocationInfo click_location);
92+
bool IsEntirelyHiddenByOverflow(void);
93+
bool ScrollWithinOverflow(const LocationInfo element_location);
9294
bool AppendFrameDetails(std::vector<LocationInfo>* frame_locations);
9395
int GetContainingDocument(const bool use_dom_node, IHTMLDocument2** doc);
9496
int GetDocumentFromWindow(IHTMLWindow2* parent_window,

0 commit comments

Comments
 (0)