Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7cfd0a7

Browse filesBrowse files
committed
fix: glitches on page scroll or processing elements hover
1 parent 0fe6b9c commit 7cfd0a7
Copy full SHA for 7cfd0a7

File tree

Expand file treeCollapse file tree

2 files changed

+121
-51
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+121
-51
lines changed

‎src/widget/html_widget.cpp

Copy file name to clipboardExpand all lines: src/widget/html_widget.cpp
+32-26Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,15 @@ void html_widget::snapshot_vfunc(const Glib::RefPtr<Gtk::Snapshot>& snapshot)
114114
return;
115115
}
116116

117-
auto allocation = get_allocation();
118-
auto cr = snapshot->append_cairo(Gdk::Rectangle(0, 0, allocation.get_width(), allocation.get_height()));
119-
if(m_draw_buffer.get_cairo_surface())
120117
{
121-
cr->scale(1.0 / m_draw_buffer.get_scale_factor(), 1.0 / m_draw_buffer.get_scale_factor());
122-
cairo_set_source_surface(cr->cobj(), m_draw_buffer.get_cairo_surface(), 0, 0);
123-
cr->paint();
118+
auto allocation = get_allocation();
119+
auto cr = snapshot->append_cairo(Gdk::Rectangle(0, 0, allocation.get_width(), allocation.get_height()));
120+
if(m_draw_buffer.get_cairo_surface())
121+
{
122+
cr->scale(1.0 / m_draw_buffer.get_scale_factor(), 1.0 / m_draw_buffer.get_scale_factor());
123+
cairo_set_source_surface(cr->cobj(), m_draw_buffer.get_cairo_surface(), 0, 0);
124+
cr->paint();
125+
}
124126
}
125127

126128
snapshot_child(*m_vscrollbar, snapshot);
@@ -129,10 +131,10 @@ void html_widget::snapshot_vfunc(const Glib::RefPtr<Gtk::Snapshot>& snapshot)
129131

130132
void html_widget::get_client_rect(litehtml::position& client) const
131133
{
132-
client.x = (int) (m_hadjustment->get_value() - m_hadjustment->get_lower());
133-
client.y = (int) (m_vadjustment->get_value() - m_vadjustment->get_lower());
134-
client.width = (int) (m_hadjustment->get_page_size());
135-
client.height = (int) (m_vadjustment->get_page_size());
134+
client.x = m_draw_buffer.get_left();
135+
client.y = m_draw_buffer.get_top();
136+
client.width = m_draw_buffer.get_width();
137+
client.height = m_draw_buffer.get_height();
136138
}
137139

138140
void html_widget::set_caption(const std::string& caption)
@@ -214,8 +216,8 @@ void html_widget::on_button_press_event(int /* n_press */, double x, double y)
214216
auto page = current_page();
215217
if (page)
216218
{
217-
page->on_lbutton_down( (int) (x + m_hadjustment->get_value()),
218-
(int) (y + m_vadjustment->get_value()),
219+
page->on_lbutton_down( (int) (x + m_draw_buffer.get_left()),
220+
(int) (y + m_draw_buffer.get_top()),
219221
(int) x, (int) y);
220222
}
221223
}
@@ -225,8 +227,8 @@ void html_widget::on_button_release_event(int /* n_press */, double x, double y)
225227
auto page = current_page();
226228
if(page)
227229
{
228-
page->on_lbutton_up((int) (x + m_hadjustment->get_value()),
229-
(int) (y + m_vadjustment->get_value()),
230+
page->on_lbutton_up((int) (x + m_draw_buffer.get_left()),
231+
(int) (y + m_draw_buffer.get_top()),
230232
(int) x, (int) y);
231233
}
232234
}
@@ -269,8 +271,8 @@ void html_widget::on_mouse_move(double x, double y)
269271
std::shared_ptr<litebrowser::web_page> page = current_page();
270272
if(page)
271273
{
272-
page->on_mouse_over((int) (x + m_hadjustment->get_value()),
273-
(int) (y + m_vadjustment->get_value()),
274+
page->on_mouse_over((int) (x + m_draw_buffer.get_left()),
275+
(int) (y + m_draw_buffer.get_top()),
274276
(int) x, (int) y);
275277
}
276278
}
@@ -388,7 +390,7 @@ long html_widget::render_measure(int number)
388390
auto t1 = std::chrono::high_resolution_clock::now();
389391
for (int i = 0; i < number; i++)
390392
{
391-
page->render(m_rendered_width);
393+
page->render(m_draw_buffer.get_width());
392394
}
393395
auto t2 = std::chrono::high_resolution_clock::now();
394396
return (std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1)).count();
@@ -402,16 +404,20 @@ void html_widget::size_allocate_vfunc(int width, int height, int /* baseline */)
402404
std::shared_ptr<litebrowser::web_page> page = current_page();
403405
if(page)
404406
{
405-
m_rendered_width = width;
406-
page->media_changed();
407-
page->render(m_rendered_width);
408-
update_view_port(page);
409-
m_draw_buffer.on_size_allocate(page, width, height);
410-
queue_draw();
407+
if(m_rendered_width != width || m_rendered_height != height)
408+
{
409+
m_rendered_width = width;
410+
m_rendered_height = height;
411+
m_draw_buffer.on_size_allocate(page, width, height);
412+
page->media_changed();
413+
page->render(m_rendered_width);
414+
update_view_port(page);
415+
m_draw_buffer.redraw(page);
416+
queue_draw();
417+
}
411418
} else
412419
{
413420
m_draw_buffer.on_size_allocate(page, width, height);
414-
m_rendered_width = width;
415421
}
416422

417423
}
@@ -562,7 +568,7 @@ void html_widget::redraw_boxes(const litehtml::position::vector& boxes)
562568

563569
int html_widget::get_render_width()
564570
{
565-
return get_width();
571+
return m_draw_buffer.get_width();
566572
}
567573

568574
void html_widget::on_page_loaded(uint64_t web_page_id)
@@ -647,7 +653,7 @@ void html_widget::render()
647653
std::shared_ptr<litebrowser::web_page> page = current_page();
648654
if(page)
649655
{
650-
page->render(m_rendered_width);
656+
page->render(m_draw_buffer.get_width());
651657
update_view_port(page);
652658
m_draw_buffer.redraw(page);
653659
queue_draw();

‎src/widget/html_widget.h

Copy file name to clipboardExpand all lines: src/widget/html_widget.h
+89-25Lines changed: 89 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,11 @@ class html_widget_notifier : public litebrowser::browser_notify_interface
198198
}
199199
};
200200

201+
/// @brief Draw Buffer Class
202+
///
203+
/// This class performs the draw operations into the cairo surface.
204+
/// The application draws everything to the buffer, then buffer are
205+
/// drawn on widged or window.
201206
class draw_buffer
202207
{
203208
cairo_surface_t* m_draw_buffer = nullptr;
@@ -235,6 +240,9 @@ class draw_buffer
235240
[[nodiscard]]
236241
double get_scale_factor() const { return m_scale_factor; }
237242

243+
/// @brief Set scale factor for draw buffer
244+
/// @param page the webpage to be redraw if required
245+
/// @param scale the scale factor to be applied
238246
void set_scale_factor(std::shared_ptr<litebrowser::web_page> page, double scale)
239247
{
240248
if(m_scale_factor != scale)
@@ -255,6 +263,22 @@ class draw_buffer
255263
}
256264
}
257265

266+
/// @brief Create cairo surface for draw buffer
267+
/// @param width surface width (not scaled)
268+
/// @param height surface height (not scaled)
269+
/// @param scale_factor scale factor
270+
/// @return poiter to the cairo surface
271+
cairo_surface_t* make_surface(int width, int height, double scale_factor)
272+
{
273+
return cairo_image_surface_create(CAIRO_FORMAT_RGB24,
274+
std::ceil((double) width * scale_factor),
275+
std::ceil((double) height * scale_factor));
276+
}
277+
278+
/// @brief Creates new buffer with specified size
279+
/// @param width draw buffer width (not scaled)
280+
/// @param height draw buffer height (not scaled)
281+
/// @return true if new draw buffer was created, false if the old buffer was used
258282
bool create_draw_buffer(int width, int height)
259283
{
260284
if(m_width != width || m_height != height || !m_draw_buffer)
@@ -268,14 +292,17 @@ class draw_buffer
268292
m_draw_buffer = nullptr;
269293
if(m_width > 0 && m_height > 0)
270294
{
271-
m_draw_buffer = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
272-
std::ceil((double) m_width * m_scale_factor),
273-
std::ceil((double) m_height * m_scale_factor));
295+
m_draw_buffer = make_surface(m_width, m_height, m_scale_factor);
274296
}
297+
return true;
275298
}
276-
return m_draw_buffer != nullptr;
299+
return false;
277300
}
278301

302+
/// @brief Call this function when widget size changed
303+
/// @param page webpage to be redraw if buffer size changed
304+
/// @param width new draw buffer width
305+
/// @param height new draw buffer height
279306
void on_size_allocate(std::shared_ptr<litebrowser::web_page> page, int width, int height)
280307
{
281308
if(create_draw_buffer(width, height))
@@ -284,6 +311,14 @@ class draw_buffer
284311
}
285312
}
286313

314+
/// @brief Scrolls draw buffer to the position (left, top).
315+
///
316+
/// Note, the actual position of the draw buffer can be rounded according to the scale factor.
317+
/// Use get_left() and get_top() to know the actual position.
318+
///
319+
/// @param page webpage to be redraw if the position was changed
320+
/// @param left new horizontal position
321+
/// @param top new vertical position
287322
void on_scroll(std::shared_ptr<litebrowser::web_page> page, int left, int top)
288323
{
289324
if(m_width <= 0 || m_height <= 0 || !m_draw_buffer) return;
@@ -295,7 +330,7 @@ class draw_buffer
295330
{
296331
Gdk::Rectangle rec_current(m_left, m_top, m_width, m_height); // Current area
297332
Gdk::Rectangle rec_clean(rec_current); // Clean area
298-
Gdk::Rectangle rec_new(left, top, m_width, m_height); // New area
333+
Gdk::Rectangle rec_new(left, top, m_width, m_height); // New area
299334
rec_clean.intersect(rec_new);
300335
if(rec_clean.has_zero_area() || rec_new == rec_current)
301336
{
@@ -304,13 +339,10 @@ class draw_buffer
304339
redraw(page);
305340
} else
306341
{
307-
int scaled_width = (int) std::ceil((double) m_width * m_scale_factor);
308-
int scaled_height = (int) std::ceil((double) m_height * m_scale_factor);
309342
int surface_shift_x = (int) std::floor((double) (m_left - left) * m_scale_factor);
310343
int surface_shift_y = (int) std::floor((double) (m_top - top) * m_scale_factor);
311-
//printf("[surface_shift] top:%d m_top:%d x:%d y:%d\n", top, m_top, surface_shift_x, surface_shift_y);
312344

313-
auto new_surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, scaled_width, scaled_height);
345+
auto new_surface = make_surface(m_width, m_height, m_scale_factor);
314346
cairo_t* cr = cairo_create(new_surface);
315347
cairo_rectangle(cr, (rec_clean.get_x() - left) * m_scale_factor - m_scale_factor,
316348
(rec_clean.get_y() - top) * m_scale_factor - m_scale_factor,
@@ -326,55 +358,84 @@ class draw_buffer
326358
m_left = left;
327359
m_top = top;
328360

329-
int right = m_left + m_width;
330-
int bottom = m_top + m_height;
331-
int clean_right = rec_clean.get_x() + rec_clean.get_width();
332-
int clean_bottom = rec_clean.get_y() + rec_clean.get_height();
361+
int right = fix_position(m_left + m_width);
362+
int bottom = fix_position(m_top + m_height);
363+
int clean_right = fix_position(rec_clean.get_x() + rec_clean.get_width());
364+
int clean_bottom = fix_position(rec_clean.get_y() + rec_clean.get_height());
333365

334366
if(rec_clean.get_x() > m_left)
335367
{
336-
redraw_area(page, m_left - 1, rec_clean.get_y() - 1, rec_clean.get_x() - m_left + 2, rec_clean.get_height() + 2);
368+
redraw_area(page, m_left,
369+
rec_clean.get_y(),
370+
rec_clean.get_x() - m_left,
371+
rec_clean.get_height());
337372
}
338373
if(clean_right < right)
339374
{
340-
redraw_area(page, clean_right - 1, rec_clean.get_y() - 1, right - clean_right + 2, rec_clean.get_height() + 2);
375+
redraw_area(page, clean_right,
376+
rec_clean.get_y(),
377+
right - clean_right,
378+
rec_clean.get_height());
341379
}
342380

343381
if(rec_clean.get_y() > m_top)
344382
{
345383
redraw_area(page, m_left,
346-
m_top - 1,
384+
m_top,
347385
m_width,
348-
rec_clean.get_y() - m_top + 2);
386+
rec_clean.get_y() - m_top);
349387
}
350388
if(clean_bottom < bottom)
351389
{
352390
redraw_area(page, m_left,
353-
clean_bottom - 1,
391+
clean_bottom,
354392
m_width,
355-
bottom - clean_bottom + 2);
393+
bottom - clean_bottom);
356394
}
357395
}
358396
}
359397
}
360398

399+
/// @brief Reraw the defined area of the buffer
400+
///
401+
/// All coordinated are not scaled. Actual rectangle could be different according to the scale factor,
402+
/// but it must always cover the requested.
403+
///
404+
/// @param page webpage to be redraw
405+
/// @param x left position of the area
406+
/// @param y top position of the area
407+
/// @param width width of the area
408+
/// @param height height of the area
361409
void redraw_area(std::shared_ptr<litebrowser::web_page> page, int x, int y, int width, int height)
362410
{
363411
if(m_draw_buffer)
364412
{
365-
// Calculate scaled position
366-
int s_x = std::floor((double) (x - m_left) * m_scale_factor);
367-
int s_y = std::floor((double) (y - m_top) * m_scale_factor);
368-
int s_width = std::ceil((double) width * m_scale_factor);
369-
int s_height = std::ceil((double) height * m_scale_factor);
413+
int fixed_left = fix_position(x - m_left);
414+
int fixed_right = fix_position(x - m_left + width);
415+
int fixed_top = fix_position(y - m_top);
416+
int fixed_bottom = fix_position(y - m_top + height);
417+
418+
if(fixed_right < x + width) fixed_right += m_min_int_position;
419+
if(fixed_bottom < y + height) fixed_bottom += m_min_int_position;
420+
421+
int fixed_x = fixed_left;
422+
int fixed_y = fixed_top;
423+
int fixed_width = fixed_right - fixed_left;
424+
int fixed_height = fixed_bottom - fixed_top;
425+
426+
int s_x = (int) std::round((double) fixed_x * m_scale_factor);
427+
int s_y = (int) std::round((double) fixed_y * m_scale_factor);
428+
int s_width = (int) std::round((double) fixed_width * m_scale_factor);
429+
int s_height = (int) std::round((double) fixed_height * m_scale_factor);
370430

371-
litehtml::position pos {x - m_left, y - m_top, width, height};
431+
litehtml::position pos {fixed_x, fixed_y, fixed_width, fixed_height};
372432
cairo_t* cr = cairo_create(m_draw_buffer);
373433

374434
// Apply clip with scaled position to avoid artifacts
375435
cairo_rectangle(cr, s_x, s_y, s_width, s_height);
376436
cairo_clip(cr);
377437

438+
// Clear rectangle with scaled position
378439
cairo_rectangle(cr, s_x, s_y, s_width, s_height);
379440
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
380441
cairo_fill(cr);
@@ -392,6 +453,8 @@ class draw_buffer
392453
}
393454
}
394455

456+
/// @brief Redraw entire buffer
457+
/// @param page webpage to be redraw
395458
void redraw(std::shared_ptr<litebrowser::web_page> page)
396459
{
397460
redraw_area(page, m_left, m_top, m_width, m_height);
@@ -429,6 +492,7 @@ class html_widget : public Gtk::Widget,
429492
public litebrowser::html_host_interface
430493
{
431494
int m_rendered_width = 0;
495+
int m_rendered_height = 0;
432496
std::mutex m_page_mutex;
433497
std::shared_ptr<litebrowser::web_page> m_current_page;
434498
std::shared_ptr<litebrowser::web_page> m_next_page;

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.