Opera 12.15 Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

viewportcontroller.cpp 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. /* -*- Mode: c++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*-
  2. *
  3. * Copyright (C) 2008-2009 Opera Software AS. All rights reserved.
  4. *
  5. * This file is part of the Opera web browser.
  6. * It may not be distributed under any circumstances.
  7. */
  8. #include "core/pch.h"
  9. #include "modules/dochand/viewportcontroller.h"
  10. #include "modules/debug/debug.h"
  11. #include "modules/display/vis_dev.h"
  12. #include "modules/doc/frm_doc.h"
  13. #include "modules/doc/html_doc.h"
  14. #include "modules/dochand/docman.h"
  15. #include "modules/dochand/fdelm.h"
  16. #include "modules/dochand/win.h"
  17. #include "modules/layout/layout_workplace.h"
  18. #include "modules/layout/traverse/traverse.h"
  19. #include "modules/logdoc/logdoc.h"
  20. #include "modules/prefs/prefsmanager/collections/pc_display.h"
  21. #ifdef NEARBY_ELEMENT_DETECTION
  22. # include "modules/widgets/finger_touch/element_expander.h"
  23. #endif // NEARBY_ELEMENT_DETECTION
  24. #ifdef RESERVED_REGIONS
  25. # include "modules/dom/domevents.h"
  26. #endif // RESERVED_REGIONS
  27. /**
  28. * This macro can be used to add an OpRect to the OP_DBG debug
  29. * statement. You need to add the debug string formatter
  30. * "(%d,%d)+%dx%d" at the correct place to use this macro.
  31. *
  32. * Example:
  33. * \code
  34. * OpRect my_rect = ...;
  35. * OP_DBG(UNI_L("rectangle: (%d,%d)+%dx%d"), _DBG_OP_RECT(my_rect));
  36. * \endcode
  37. * @param rect is a GogiRect instance.
  38. */
  39. #define _DBG_OP_RECT(rect) rect.x, rect.y, rect.width, rect.height
  40. static inline VisualDevice* GetScreenVisualDevice(Window* window)
  41. {
  42. /* Get the print preview VisualDevice if in print preview mode; otherwise
  43. get the "regular" VisualDevice. */
  44. #ifdef _PRINT_SUPPORT_
  45. if (window->GetPreviewMode())
  46. if (VisualDevice* vis_dev = window->DocManager()->GetPrintPreviewVD())
  47. {
  48. OP_ASSERT(!vis_dev->IsPrinter()); // FIXME: We wanted the print PREVIEW VisualDevice, but take a look at the GetPrintPreviewVD() implementation... :(
  49. return vis_dev;
  50. }
  51. #endif // _PRINT_SUPPORT_
  52. return window->DocManager()->GetVisualDevice();
  53. }
  54. void ViewportController::HandleVisualViewportChange(const OpRect& viewport)
  55. {
  56. OP_NEW_DBG("ViewportController::HandleVisualViewportChange", "viewport");
  57. OP_DBG((UNI_L("visual viewport: (%d,%d)+%dx%d -> (%d,%d)+%dx%d"), visual_viewport_pos.x, visual_viewport_pos.y, visual_viewport_width, visual_viewport_height, _DBG_OP_RECT(viewport)));
  58. OpRect new_visual_viewport;
  59. int negative_overflow = 0;
  60. if (visual_viewport_size_locked)
  61. {
  62. // Visual viewport size locked. Ignore new size (if any), but honor position.
  63. new_visual_viewport = GetVisualViewport();
  64. new_visual_viewport.x = viewport.x;
  65. new_visual_viewport.y = viewport.y;
  66. OP_DBG((UNI_L("Visual viewport size locked. Ignore new size (if any), but honor position. -> viewport: (%d,%d)+%dx%d"), _DBG_OP_RECT(new_visual_viewport)));
  67. }
  68. else
  69. new_visual_viewport = viewport;
  70. #ifdef NEARBY_ELEMENT_DETECTION
  71. if (window->GetElementExpander())
  72. {
  73. VisualDevice* vis_dev = GetScreenVisualDevice(window);
  74. int dx = vis_dev->ScaleToScreen(visual_viewport_pos.x - new_visual_viewport.x);
  75. int dy = vis_dev->ScaleToScreen(visual_viewport_pos.y - new_visual_viewport.y);
  76. window->GetElementExpander()->Scroll(dx, dy);
  77. }
  78. #endif // NEARBY_ELEMENT_DETECTION
  79. FramesDocument* doc = window->DocManager()->GetCurrentVisibleDoc();
  80. if (doc)
  81. {
  82. OpRect layout_viewport = doc->GetLayoutViewport();
  83. negative_overflow = doc->NegativeOverflow();
  84. OP_DBG((UNI_L("layout viewport: (%d,%d)+%dx%d; negative overflow: %d"), _DBG_OP_RECT(layout_viewport), negative_overflow));
  85. layout_viewport.x += negative_overflow;
  86. int new_layout_view_x = layout_viewport.x;
  87. int new_layout_view_y = layout_viewport.y;
  88. // Keep visual viewport within layout viewport by moving layout viewport if necessary.
  89. if (new_visual_viewport.x > visual_viewport_pos.x)
  90. {
  91. if (new_visual_viewport.x + new_visual_viewport.width > layout_viewport.x + layout_viewport.width)
  92. new_layout_view_x = new_visual_viewport.x + new_visual_viewport.width - layout_viewport.width;
  93. }
  94. else if (new_visual_viewport.x < visual_viewport_pos.x)
  95. {
  96. if (layout_viewport.x > new_visual_viewport.x)
  97. new_layout_view_x = new_visual_viewport.x;
  98. }
  99. if (new_visual_viewport.y > visual_viewport_pos.y)
  100. {
  101. if (new_visual_viewport.y + new_visual_viewport.height > layout_viewport.y + layout_viewport.height)
  102. new_layout_view_y = new_visual_viewport.y + new_visual_viewport.height - layout_viewport.height;
  103. }
  104. else if (new_visual_viewport.y < visual_viewport_pos.y)
  105. {
  106. if (layout_viewport.y > new_visual_viewport.y)
  107. new_layout_view_y = new_visual_viewport.y;
  108. }
  109. new_layout_view_x -= negative_overflow;
  110. OP_DBG((UNI_L("new layout viewport pos: (%d,%d), buffered mode: %s"),
  111. new_layout_view_x, new_layout_view_y, buffered_mode?UNI_L("yes"):UNI_L("no")));
  112. if (buffered_mode)
  113. {
  114. buffered_layout_view_x = new_layout_view_x;
  115. buffered_layout_view_y = new_layout_view_y;
  116. }
  117. else
  118. doc->SetLayoutViewPos(new_layout_view_x, new_layout_view_y);
  119. }
  120. #ifdef DEBUG_PAINT_VISUAL_VIEWPORT_RECT
  121. VisualDevice* vis_dev = GetScreenVisualDevice(window);
  122. OpRect visual_viewport = GetVisualViewport();
  123. vis_dev->Update(visual_viewport.x - negative_overflow, visual_viewport.y, visual_viewport.width, visual_viewport.height);
  124. #endif
  125. BOOL viewport_pos_changed = visual_viewport_pos.x != new_visual_viewport.x || visual_viewport_pos.y != new_visual_viewport.y;
  126. visual_viewport_pos.x = new_visual_viewport.x;
  127. visual_viewport_pos.y = new_visual_viewport.y;
  128. visual_viewport_width = new_visual_viewport.width;
  129. visual_viewport_height = new_visual_viewport.height;
  130. if (doc && viewport_pos_changed)
  131. doc->HandleDocumentEvent(ONSCROLL);
  132. #ifdef DEBUG_PAINT_VISUAL_VIEWPORT_RECT
  133. vis_dev->Update(new_visual_viewport.x - negative_overflow, new_visual_viewport.y, new_visual_viewport.width, new_visual_viewport.height);
  134. #endif
  135. }
  136. void ViewportController::GetVisualViewportSizeFromWindow(unsigned int& width, unsigned int& height)
  137. {
  138. VisualDevice* vis_dev = GetScreenVisualDevice(window);
  139. UINT32 win_width, win_height;
  140. window->GetOpWindow()->GetInnerSize(&win_width, &win_height);
  141. width = vis_dev->ScaleToDoc(win_width - vis_dev->GetVerticalScrollbarSpaceOccupied());
  142. height = vis_dev->ScaleToDoc(win_height - vis_dev->GetHorizontalScrollbarSpaceOccupied());
  143. }
  144. static OpPoint GetOffsetToToplevelDoc(FramesDocument* frm_doc)
  145. {
  146. VisualDevice* top_vd = frm_doc->GetWindow()->VisualDev();
  147. OpPoint offs(top_vd->GetRenderingViewX(), top_vd->GetRenderingViewY());
  148. for (FramesDocument* doc = frm_doc; doc; doc = doc->GetDocManager()->GetParentDoc())
  149. {
  150. FramesDocElm* frame = doc->GetDocManager()->GetFrame();
  151. VisualDevice* vd = doc->GetVisualDevice();
  152. if (frame)
  153. {
  154. offs.x += frame->GetAbsX();
  155. offs.y += frame->GetAbsY();
  156. }
  157. offs.x -= vd->GetRenderingViewX();
  158. offs.y -= vd->GetRenderingViewY();
  159. }
  160. return offs;
  161. }
  162. OpRect ViewportController::ConvertToToplevelRect(FramesDocument* frm_doc, const OpRect& local_rect)
  163. {
  164. OpRect toplevel_rect = local_rect;
  165. OpPoint offset = GetOffsetToToplevelDoc(frm_doc);
  166. toplevel_rect.OffsetBy(offset.x, offset.y);
  167. return toplevel_rect;
  168. }
  169. OpRect ViewportController::ConvertToLocalRect(FramesDocument* frm_doc, const OpRect& toplevel_rect)
  170. {
  171. OpRect local_rect = toplevel_rect;
  172. OpPoint offset = GetOffsetToToplevelDoc(frm_doc);
  173. local_rect.OffsetBy(-offset.x, -offset.y);
  174. return local_rect;
  175. }
  176. FramesDocument* ViewportController::FindDocumentAtPosAndTranslate(OpPoint& p, BOOL allow_svg /* = TRUE*/)
  177. {
  178. FramesDocument* d = window->DocManager()->GetCurrentVisibleDoc();
  179. if (!d)
  180. return NULL;
  181. VisualDevice* vd = d->GetVisualDevice();
  182. OpPoint screen_pos = vd->ScaleToScreen(p - vd->GetRenderingViewport().TopLeft()) + vd->GetPosOnScreen();
  183. FindElementAtScreenPosAndTranslate(screen_pos, d, p);
  184. #ifdef SVG_SUPPORT
  185. if (!allow_svg)
  186. while (d && d->GetLogicalDocument() && d->GetLogicalDocument()->GetDocRoot() &&
  187. d->GetLogicalDocument()->GetDocRoot()->IsMatchingType(Markup::SVGE_SVG, NS_SVG))
  188. {
  189. d = d->GetParentDoc();
  190. p = vd->ScaleToDoc(screen_pos - vd->GetPosOnScreen()) + vd->GetRenderingViewport().TopLeft();
  191. }
  192. #endif
  193. return d;
  194. }
  195. HTML_Element* ViewportController::FindElementAtScreenPosAndTranslate(const OpPoint& screen_pos, FramesDocument* &target_doc, OpPoint &document_pos)
  196. {
  197. HTML_Element* target = NULL;
  198. target_doc = window->DocManager()->GetCurrentVisibleDoc();
  199. if (!target_doc)
  200. return NULL;
  201. // Loop over the document hierarchy to try to find the target element. An IntersectionObject is used to find an element within a document.
  202. // The IntersectionObject won't enter subdocuments. For iframes it returns the HTML_Element of the iframe, and for framesets it does nothing.
  203. // Thus iframes and framesets need different code paths. Either way, when a subdocument is encountered, the loop is restarted with
  204. // the target_doc set to the subdocument. That way, the document position is always recalculated to match the current target_doc and
  205. // additional subdocuments will be entered when needed.
  206. while (TRUE)
  207. {
  208. VisualDevice* vd = target_doc->GetVisualDevice();
  209. document_pos = vd->ScaleToDoc(screen_pos - vd->GetPosOnScreen()) + vd->GetRenderingViewport().TopLeft();
  210. if (target_doc->IsFrameDoc())
  211. {
  212. // The document contains a frameset. Intersection objects won't work with framesets, so we need to manually locate which subdocument the position is in.
  213. FramesDocElm* fdelm = target_doc->GetFrmDocRoot();
  214. while (fdelm)
  215. {
  216. if (fdelm->GetCurrentDoc())
  217. {
  218. OpRect frame_rect(fdelm->GetAbsX(), fdelm->GetAbsY(), fdelm->GetWidth(), fdelm->GetHeight());
  219. if (frame_rect.Contains(document_pos))
  220. break;
  221. }
  222. fdelm = fdelm->Next();
  223. }
  224. if (fdelm)
  225. {
  226. // Found a suitable subdocument. Set target_doc and restart the loop to enter the subdocument.
  227. target_doc = fdelm->GetCurrentDoc();
  228. continue;
  229. }
  230. }
  231. // It is not a frameset, or we didn't find a matching frame -> try an IntersectionObject.
  232. HLDocProfile* hld_profile = target_doc->GetHLDocProfile();
  233. if (!hld_profile || !hld_profile->GetRoot())
  234. break;
  235. IntersectionObject intersection(target_doc, LayoutCoord(document_pos.x), LayoutCoord(document_pos.y), TRUE);
  236. intersection.Traverse(hld_profile->GetRoot());
  237. Box* inner_box = intersection.GetInnerBox();
  238. if (!inner_box)
  239. break;
  240. target = inner_box->GetHtmlElement();
  241. FramesDocElm* fdelm = FramesDocElm::GetFrmDocElmByHTML(target);
  242. if (!fdelm || !fdelm->GetCurrentDoc())
  243. break; // The loop normally ends here. We found a target element and it is not an iframe!
  244. // The position is at an iframe with a document. Set target_doc and restart the loop to enter the subdocument.
  245. target_doc = fdelm->GetCurrentDoc();
  246. target = NULL;
  247. }
  248. return target;
  249. }
  250. #ifdef PAGED_MEDIA_SUPPORT
  251. void ViewportController::SignalPageChange(int current, int total)
  252. {
  253. if (current_page_number != current || total_page_count != total)
  254. {
  255. current_page_number = current;
  256. total_page_count = total;
  257. viewport_info_listener->OnPageChanged(current, total);
  258. }
  259. }
  260. #endif // PAGED_MEDIA_SUPPORT
  261. void ViewportController::SetViewportRequestListener(OpViewportRequestListener* listener)
  262. {
  263. viewport_request_listener = listener ? listener : &default_viewport_request_listener;
  264. }
  265. void ViewportController::SetViewportInfoListener(OpViewportInfoListener* listener)
  266. {
  267. viewport_info_listener = listener ? listener : &null_viewport_info_listener;
  268. }
  269. void ViewportController::LockVisualViewportSize(BOOL lock)
  270. {
  271. OP_NEW_DBG("ViewportController::LockVisualViewportSize", "viewport");
  272. OP_DBG((UNI_L("lock: %s"), (lock?UNI_L("yes"):UNI_L("no"))));
  273. if (!visual_viewport_size_locked != !lock)
  274. {
  275. if (!lock)
  276. // Set visual viewport size to current window size when unlocking it.
  277. GetVisualViewportSizeFromWindow(visual_viewport_width, visual_viewport_height);
  278. visual_viewport_size_locked = lock;
  279. }
  280. #ifdef DEBUG_PAINT_VISUAL_VIEWPORT_RECT
  281. GetScreenVisualDevice(window)->UpdateAll();
  282. #endif // DEBUG_PAINT_VISUAL_VIEWPORT_RECT
  283. }
  284. void ViewportController::SetBufferedMode(BOOL buffered_mode)
  285. {
  286. if (this->buffered_mode != buffered_mode)
  287. {
  288. if (!buffered_mode)
  289. FlushBuffer();
  290. this->buffered_mode = buffered_mode;
  291. }
  292. }
  293. void ViewportController::FlushBuffer()
  294. {
  295. OP_NEW_DBG("ViewportController::FlushBuffer", "viewport");
  296. if (buffered_mode)
  297. {
  298. OpRect updated_area;
  299. if (buffered_layout_view_x != INT_MIN)
  300. {
  301. if (FramesDocument* doc = window->DocManager()->GetCurrentVisibleDoc())
  302. {
  303. OP_DBG((UNI_L("flush layout viewport position: %d,%d"),
  304. buffered_layout_view_x, buffered_layout_view_y));
  305. updated_area = doc->SetLayoutViewPos(buffered_layout_view_x, buffered_layout_view_y);
  306. }
  307. buffered_layout_view_x = INT_MIN;
  308. buffered_layout_view_y = INT_MIN;
  309. }
  310. if (buffered_rendering_view_x != INT_MIN)
  311. {
  312. OP_DBG((UNI_L("flush rendering viewport position: %d,%d"),
  313. buffered_rendering_view_x, buffered_rendering_view_y));
  314. GetScreenVisualDevice(window)->SetRenderingViewPos(buffered_rendering_view_x, buffered_rendering_view_y, FALSE, &updated_area);
  315. buffered_rendering_view_x = INT_MIN;
  316. buffered_rendering_view_y = INT_MIN;
  317. }
  318. }
  319. }
  320. void ViewportController::SetDesktopLayoutViewportSize(unsigned int width, unsigned int height)
  321. {
  322. OP_NEW_DBG("ViewportController::SetDesktopLayoutViewportSize", "viewport");
  323. OP_DBG((UNI_L("size: %dx%d"), width, height));
  324. if (desktop_layout_width != width || desktop_layout_height != height)
  325. {
  326. desktop_layout_width = width;
  327. desktop_layout_height = height;
  328. if (FramesDocument* doc = window->DocManager()->GetCurrentVisibleDoc())
  329. doc->RecalculateLayoutViewSize(FALSE);
  330. }
  331. }
  332. OpRect ViewportController::GetVisualViewport()
  333. {
  334. OpRect visual_viewport;
  335. visual_viewport.x = visual_viewport_pos.x;
  336. visual_viewport.y = visual_viewport_pos.y;
  337. if (visual_viewport_size_locked)
  338. // Let visual viewport size follow window size
  339. GetVisualViewportSizeFromWindow(visual_viewport_width, visual_viewport_height);
  340. visual_viewport.width = visual_viewport_width;
  341. visual_viewport.height = visual_viewport_height;
  342. return visual_viewport;
  343. }
  344. void ViewportController::SetVisualViewport(const OpRect& viewport)
  345. {
  346. OP_NEW_DBG("ViewportController::SetVisualViewport", "viewport");
  347. OP_DBG((UNI_L("viewport: (%d,%d)+%dx%d"), _DBG_OP_RECT(viewport)));
  348. HandleVisualViewportChange(viewport);
  349. }
  350. void ViewportController::SetVisualViewportPos(const OpPoint& pos)
  351. {
  352. OP_NEW_DBG("ViewportController::SetVisualViewportPos", "viewport");
  353. OP_DBG((UNI_L("viewport: (%d,%d)"), pos.x, pos.y));
  354. OpRect new_viewport = GetVisualViewport();
  355. new_viewport.x = pos.x;
  356. new_viewport.y = pos.y;
  357. HandleVisualViewportChange(new_viewport);
  358. }
  359. #ifdef PAGED_MEDIA_SUPPORT
  360. void ViewportController::SetCurrentPageNumber(int page_number)
  361. {
  362. if (FramesDocument* doc = window->DocManager()->GetCurrentVisibleDoc())
  363. if (LogicalDocument* logdoc = doc->GetLogicalDocument())
  364. {
  365. LayoutWorkplace* workplace = logdoc->GetLayoutWorkplace();
  366. int page_count = workplace->GetTotalPageCount();
  367. if (page_number >= page_count)
  368. page_number = page_count - 1;
  369. if (page_number < 0)
  370. page_number = 0;
  371. workplace->SetCurrentPageNumber(page_number, VIEWPORT_CHANGE_REASON_INPUT_ACTION);
  372. }
  373. }
  374. int ViewportController::GetCurrentPageNumber()
  375. {
  376. if (FramesDocument* doc = window->DocManager()->GetCurrentVisibleDoc())
  377. if (LogicalDocument* logdoc = doc->GetLogicalDocument())
  378. return logdoc->GetLayoutWorkplace()->GetCurrentPageNumber();
  379. return -1;
  380. }
  381. int ViewportController::GetTotalPageCount()
  382. {
  383. if (FramesDocument* doc = window->DocManager()->GetCurrentVisibleDoc())
  384. if (LogicalDocument* logdoc = doc->GetLogicalDocument())
  385. return logdoc->GetLayoutWorkplace()->GetTotalPageCount();
  386. return -1;
  387. }
  388. #endif // PAGED_MEDIA_SUPPORT
  389. void ViewportController::SetTextParagraphWidthLimit(unsigned int max_paragraph_width, const OpPoint* pos)
  390. {
  391. OP_NEW_DBG("ViewportController::SetTextParagraphWidthLimit", "viewport");
  392. OP_DBG((UNI_L("max paragraph width: %d; position: (%d,%d)"), max_paragraph_width, (pos ? pos->x : 0), (pos ? pos->y : 0)));
  393. if (window->GetLimitParagraphWidth() && (unsigned int) this->max_paragraph_width == max_paragraph_width)
  394. return;
  395. if (pos)
  396. {
  397. // unconstify
  398. OpPoint tmp_point = *pos;
  399. FramesDocument* fdoc = FindDocumentAtPosAndTranslate(tmp_point);
  400. if (fdoc)
  401. {
  402. HTML_Document* hdoc = fdoc->GetHtmlDocument();
  403. OP_ASSERT(hdoc);
  404. if (hdoc)
  405. hdoc->SaveScrollToElement(tmp_point);
  406. }
  407. }
  408. this->max_paragraph_width = max_paragraph_width;
  409. window->SetLimitParagraphWidth(TRUE);
  410. }
  411. void ViewportController::DisableTextParagraphWidthLimit(const OpPoint* pos)
  412. {
  413. OP_NEW_DBG("ViewportController::DisableTextParagraphWidthLimit", "viewport");
  414. OP_DBG((UNI_L("position: (%d,%d)"), (pos ? pos->x : 0), (pos ? pos->y : 0)));
  415. if (!window->GetLimitParagraphWidth())
  416. return;
  417. if (pos)
  418. {
  419. // unconstify
  420. OpPoint tmp_point = *pos;
  421. FramesDocument* fdoc = FindDocumentAtPosAndTranslate(tmp_point);
  422. OP_ASSERT(fdoc);
  423. if (fdoc)
  424. {
  425. HTML_Document* hdoc = fdoc->GetHtmlDocument();
  426. OP_ASSERT(hdoc);
  427. if (hdoc)
  428. hdoc->SaveScrollToElement(tmp_point);
  429. }
  430. }
  431. window->SetLimitParagraphWidth(FALSE);
  432. }
  433. OpRect ViewportController::GetRenderingViewport()
  434. {
  435. VisualDevice* vis_dev = GetScreenVisualDevice(window);
  436. OpRect viewport = vis_dev->GetRenderingViewport();
  437. if (FramesDocument* doc = window->DocManager()->GetCurrentVisibleDoc())
  438. viewport.x += doc->NegativeOverflow();
  439. return viewport;
  440. }
  441. void ViewportController::SetRenderingViewportPos(const OpPoint& pos)
  442. {
  443. OP_NEW_DBG("ViewportController::SetRenderingViewportPos", "viewport");
  444. OP_DBG((UNI_L("position: (%d,%d)"), pos.x, pos.y));
  445. VisualDevice* vis_dev = GetScreenVisualDevice(window);
  446. int negative_overflow = 0;
  447. if (FramesDocument* doc = window->DocManager()->GetCurrentVisibleDoc())
  448. negative_overflow = doc->NegativeOverflow();
  449. OpPoint new_pos(pos.x - negative_overflow, pos.y);
  450. if (buffered_mode)
  451. {
  452. buffered_rendering_view_x = new_pos.x;
  453. buffered_rendering_view_y = new_pos.y;
  454. }
  455. else
  456. vis_dev->SetRenderingViewPos(new_pos.x, new_pos.y);
  457. }
  458. void ViewportController::SetRenderingScale(unsigned int scale_percentage)
  459. {
  460. OP_NEW_DBG("ViewportController::SetRenderingScale", "viewport");
  461. OP_DBG((UNI_L("scale: %d%%"), scale_percentage));
  462. window->SetTrueZoom(TRUE);
  463. window->SetScale(scale_percentage);
  464. }
  465. void ViewportController::SetTrueZoomBaseScale(unsigned int scale_percentage)
  466. {
  467. window->SetTrueZoomBaseScale(scale_percentage);
  468. }
  469. OpRect ViewportController::GetLayoutViewport()
  470. {
  471. if (FramesDocument* doc = window->DocManager()->GetCurrentVisibleDoc())
  472. {
  473. OpRect viewport = doc->GetLayoutViewport();
  474. viewport.x += doc->NegativeOverflow();
  475. return viewport;
  476. }
  477. else
  478. return OpRect();
  479. }
  480. void ViewportController::GetDocumentSize(unsigned int* width, unsigned int* height)
  481. {
  482. if (FramesDocument* doc = window->DocManager()->GetCurrentVisibleDoc())
  483. {
  484. *width = doc->Width() + doc->NegativeOverflow();
  485. *height = doc->Height();
  486. }
  487. else
  488. {
  489. *width = 0;
  490. *height = 0;
  491. }
  492. }
  493. void ViewportController::GetParagraphRects(const OpRect& rect, Head* paragraph_rects)
  494. {
  495. if (FramesDocument* doc = window->DocManager()->GetCurrentVisibleDoc())
  496. if (LogicalDocument* logdoc = doc->GetLogicalDocument())
  497. if (LayoutWorkplace* workplace = logdoc->GetLayoutWorkplace())
  498. {
  499. RAISE_IF_MEMORY_ERROR(workplace->GetParagraphList(rect, *paragraph_rects));
  500. int negative_overflow = doc->NegativeOverflow();
  501. for (OpRectListItem* item = (OpRectListItem*) paragraph_rects->First(); item; item = item->Suc())
  502. item->rect.x += negative_overflow;
  503. }
  504. }
  505. #ifdef RESERVED_REGIONS
  506. /**
  507. * ReservedRectFinder traverses a document hierarchy and gathers a list of all reserved rectangles found.
  508. */
  509. class ReservedRectFinder
  510. {
  511. public:
  512. /**
  513. * Retrieve list of all reserved rectangles in the document hierarchy.
  514. *
  515. * @param[in] root_document Document from which to initiate search.
  516. * @param[in] search_rect Rectangle defining region in which to look for reserved rectangles.
  517. * @param[out] reserved_region Region structure where found reserved rectangles will be stored.
  518. *
  519. * @return OpStatus::OK on success, OpStatus::ERR_NO_MEMORY on OOM.
  520. */
  521. OP_STATUS FindReservedRects(FramesDocument* root_document, const OpRect& search_rect, OpRegion& reserved_region);
  522. protected:
  523. OP_STATUS GetReservedRects(FramesDocument* document, const OpRect& search_rect, OpRegion& region);
  524. };
  525. OP_STATUS ReservedRectFinder::FindReservedRects(FramesDocument* root_document, const OpRect& search_rect, OpRegion& reserved_region)
  526. {
  527. RETURN_IF_ERROR(GetReservedRects(root_document, search_rect, reserved_region));
  528. DocumentTreeIterator it(root_document);
  529. BOOL skip_children = FALSE;
  530. while (it.Next(skip_children))
  531. {
  532. FramesDocElm* frame = it.GetFramesDocElm();
  533. skip_children = FALSE;
  534. if (FramesDocument* doc = frame->GetCurrentDoc())
  535. {
  536. /* Obtain the local document's position in the top level document space. */
  537. OpPoint translation = frame->GetAbsPos().GetTranslation();
  538. for (FramesDocument* fd = doc->GetParentDoc(); fd && fd != root_document; fd = fd->GetParentDoc())
  539. if (FramesDocElm* fde = fd->GetDocManager()->GetFrame())
  540. {
  541. VisualDevice* vd = fde->GetVisualDevice();
  542. translation.x += fde->GetAbsX() - vd->GetRenderingViewX();
  543. translation.y += fde->GetAbsY() - vd->GetRenderingViewY();
  544. }
  545. /* Clip against search rect. */
  546. VisualDevice* vis_dev = doc->GetVisualDevice();
  547. OpRect rect(translation.x, translation.y, vis_dev->GetRenderingViewWidth(), vis_dev->GetRenderingViewHeight());
  548. rect.IntersectWith(search_rect);
  549. if (!rect.IsEmpty())
  550. {
  551. /* Translate into local document space. */
  552. rect.x += vis_dev->GetRenderingViewX() - translation.x;
  553. rect.y += vis_dev->GetRenderingViewY() - translation.y;
  554. OpRegion region;
  555. RETURN_IF_ERROR(GetReservedRects(doc, rect, region));
  556. /* Clip and translate found regions back to top level document space. */
  557. region.Translate(doc->NegativeOverflow(), 0);
  558. region.IntersectWith(rect);
  559. region.Translate(translation.x - vis_dev->GetRenderingViewX(), translation.y - vis_dev->GetRenderingViewY());
  560. reserved_region.IncludeRegion(region);
  561. }
  562. else
  563. skip_children = TRUE;
  564. }
  565. }
  566. return OpStatus::OK;
  567. }
  568. OP_STATUS ReservedRectFinder::GetReservedRects(FramesDocument* document, const OpRect& search_rect, OpRegion& region)
  569. {
  570. return document->GetReservedRegion(search_rect, region);
  571. }
  572. OP_STATUS ViewportController::GetReservedRegion(const OpRect& rect, OpRegion& reserved_region)
  573. {
  574. if (FramesDocument* doc = window->DocManager()->GetCurrentVisibleDoc())
  575. {
  576. ReservedRectFinder finder;
  577. return finder.FindReservedRects(doc, rect, reserved_region);
  578. }
  579. return OpStatus::OK;
  580. }
  581. #endif // RESERVED_REGIONS
  582. #undef _DBG_OP_RECT