From 06f9083bdeb085b7b9de762fa029f6519e142dbe Mon Sep 17 00:00:00 2001 From: Rodrigo Arias Mallo Date: Sun, 9 Jun 2024 21:52:14 +0200 Subject: Add support for zoom factor Allows zooming in and out of pages by changing the size of all elements, including font size, images and tables. The initial zoom is specified in the "zoom_factor" option of dillorc. Use the new shortcuts Ctrl+ and Ctrl- to adjust the zoom of the current page and Ctrl 0 to reset it to 100%. When a new tab or window is opened, the current zoom factor is inherited. Each tab retains its own zoom factor. Fixes: https://github.com/dillo-browser/dillo/issues/21 --- ChangeLog | 1 + dillorc | 4 ++++ doc/user_help.in.html | 14 ++++++++++++ src/bw.c | 3 +++ src/bw.h | 15 +++++++++++++ src/html.cc | 2 +- src/keys.cc | 5 +++++ src/keys.hh | 6 +++++- src/keysrc | 8 +++++++ src/plain.cc | 3 ++- src/prefs.c | 1 + src/prefs.h | 1 + src/prefsparser.cc | 3 ++- src/styleengine.cc | 30 ++++++++++++++------------ src/styleengine.hh | 15 ++++++++++++- src/ui.cc | 9 ++++++++ src/uicmd.cc | 59 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/uicmd.hh | 15 +++++++++++++ src/web.cc | 8 ++++--- 19 files changed, 178 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index f3b65cc0..ec0fe050 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,7 @@ dillo-3.2.0 [Not released yet] Patches: Alex, Rodrigo Arias Mallo +- Ignore empty page title for tab labels. Fix segfault when clicking the "Done" button in downloads dialog. + Add zoom support using Ctrl +/-/0 and the "zoom_factor" option. Patches: Rodrigo Arias Mallo dillo-3.1.1 [Jun 8, 2024] diff --git a/dillorc b/dillorc index 72f6862e..0b888466 100644 --- a/dillorc +++ b/dillorc @@ -95,6 +95,10 @@ # differentiates between tables and, say, textblocks (in some cases). #adjust_table_min_width=YES +# Sets the initial zoom factor, which scales the size of all HTML elements. +# zoom_factor=1.5 +#zoom_factor=1.0 + #------------------------------------------------------------------------- # PENALTIES #------------------------------------------------------------------------- diff --git a/doc/user_help.in.html b/doc/user_help.in.html index 66480681..e6dbc29d 100644 --- a/doc/user_help.in.html +++ b/doc/user_help.in.html @@ -90,6 +90,7 @@ keywords. Generated for version __VERSION__.

  • Scrolling
  • Find text
  • Copy and paste
  • +
  • Zoom
  • Navigation @@ -235,6 +236,16 @@ If you want to paste an URL into Dillo, do it on the "clear-URL" button (the "X" next to the location bar).

    +

    Zoom

    +

    +You can increase or decrease the size of the elements of a page by changing the +zoom factor. Use Ctrl + to increase the size, Ctrl - +to decrease it and Ctrl 0 to reset the value to 100%. +

    +The initial zoom factor is specified by the zoom_factor option in +the dillorc configuration file. When a new tab or window +is opened, the current zoom factor value is inherited. +

    This section focuses on how to navigate to other pages by following hyperlinks, using bookmarks, typing or pasting a new URL or using the history. @@ -778,6 +789,9 @@ The list of default bindings is given in the following table. Ctrl-U View source Ctrl-B Bookmarks View bookmarks Ctrl-Q Quit Quit dillo +Ctrl-+ or Ctrl-= Bigger Zoom in +Ctrl-- Smaller Zoom out +Ctrl-0 100% Reset zoom to 100% Back or "," < Previous page Shift-Back or "." > Next page Alt-F File File menu diff --git a/src/bw.c b/src/bw.c index cd9588c3..ae399028 100644 --- a/src/bw.c +++ b/src/bw.c @@ -2,6 +2,7 @@ * File: bw.c * * Copyright (C) 2006-2007 Jorge Arellano Cid + * Copyright (C) 2024 Rodrigo Arias Mallo * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -74,6 +75,8 @@ BrowserWindow *a_Bw_new() bw->num_page_bugs = 0; bw->page_bugs = dStr_new(""); + bw->zoom = 1.0; + /* now that the bw is made, let's customize it.. */ //Interface_browser_window_customize(bw); diff --git a/src/bw.h b/src/bw.h index 076c798e..a043e1ea 100644 --- a/src/bw.h +++ b/src/bw.h @@ -1,3 +1,15 @@ +/* + * File: bw.h + * + * Copyright (C) 2006-2011 Jorge Arellano Cid + * Copyright (C) 2024 Rodrigo Arias Mallo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + */ + #ifndef __BW_H__ #define __BW_H__ @@ -57,6 +69,9 @@ typedef struct { /** HTML-bugs detected at parse time */ int num_page_bugs; Dstr *page_bugs; + + /* Zoom factor */ + float zoom; } BrowserWindow; diff --git a/src/html.cc b/src/html.cc index 944977b2..471a1afa 100644 --- a/src/html.cc +++ b/src/html.cc @@ -461,7 +461,7 @@ DilloHtml::DilloHtml(BrowserWindow *p_bw, const DilloUrl *url, DocType = DT_NONE; /* assume Tag Soup 0.0! :-) */ DocTypeVersion = 0.0f; - styleEngine = new StyleEngine (HT2LT (this), page_url, base_url); + styleEngine = new StyleEngine (HT2LT (this), page_url, base_url, bw->zoom); cssUrls = new misc::SimpleVector (1); diff --git a/src/keys.cc b/src/keys.cc index a512b8ea..7346706e 100644 --- a/src/keys.cc +++ b/src/keys.cc @@ -2,6 +2,7 @@ * Key parser * * Copyright (C) 2009 Jorge Arellano Cid + * Copyright (C) 2024 Rodrigo Arias Mallo * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -136,6 +137,10 @@ static const KeyBinding_t default_keys[] = { { "right" , KEYS_RIGHT , 0 , FL_Right }, { "top" , KEYS_TOP , 0 , FL_Home }, { "bottom" , KEYS_BOTTOM , 0 , FL_End }, + { "zoom-in" , KEYS_ZOOM_IN , FL_CTRL , '+' }, + { "zoom-in" , KEYS_ZOOM_IN , FL_CTRL , '=' /* US + */ }, + { "zoom-out" , KEYS_ZOOM_OUT , FL_CTRL , '-' }, + { "zoom-reset" , KEYS_ZOOM_RESET , FL_CTRL , '0' }, }; static Dlist *bindings; diff --git a/src/keys.hh b/src/keys.hh index 8d2ec53c..22c337ac 100644 --- a/src/keys.hh +++ b/src/keys.hh @@ -2,6 +2,7 @@ * Key parser * * Copyright (C) 2009 Jorge Arellano Cid + * Copyright (C) 2024 Rodrigo Arias Mallo * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -47,7 +48,10 @@ typedef enum { KEYS_LEFT, KEYS_RIGHT, KEYS_TOP, - KEYS_BOTTOM + KEYS_BOTTOM, + KEYS_ZOOM_IN, + KEYS_ZOOM_OUT, + KEYS_ZOOM_RESET } KeysCommand_t; class Keys { diff --git a/src/keysrc b/src/keysrc index 64d527d6..bcfbb039 100644 --- a/src/keysrc +++ b/src/keysrc @@ -84,6 +84,14 @@ # "save" the current page. #(save has no default binding) +# "zoom-in" increases the zoom by 10% (make elements bigger). +#+ = zoom-in +#= = zoom-in +# "zoom-out" decreases the zoom by 10% (make elements smaller). +#- = zoom-out +# "zoom-reset" resets the zoom to 100%. +#0 = zoom-reset + #-------------------------------------------------------------------- # MOTION COMMANDS #-------------------------------------------------------------------- diff --git a/src/plain.cc b/src/plain.cc index 2783f0b1..8be30cb7 100644 --- a/src/plain.cc +++ b/src/plain.cc @@ -2,6 +2,7 @@ * File: plain.cc * * Copyright (C) 2005-2007 Jorge Arellano Cid + * Copyright (C) 2024 Rodrigo Arias Mallo * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -97,7 +98,7 @@ DilloPlain::DilloPlain(BrowserWindow *p_bw) Layout *layout = (Layout*) bw->render_layout; // TODO (1x) No URL? - StyleEngine styleEngine (layout, NULL, NULL); + StyleEngine styleEngine (layout, NULL, NULL, bw->zoom); styleEngine.startElement ("body", bw); styleEngine.startElement ("pre", bw); diff --git a/src/prefs.c b/src/prefs.c index e7f735ed..6d265adc 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -47,6 +47,7 @@ void a_Prefs_init(void) prefs.focus_new_tab = TRUE; prefs.font_cursive = dStrdup(PREFS_FONT_CURSIVE); prefs.font_factor = 1.0; + prefs.zoom_factor = 1.0; prefs.font_max_size = 100; prefs.font_min_size = 6; prefs.font_fantasy = dStrdup(PREFS_FONT_FANTASY); diff --git a/src/prefs.h b/src/prefs.h index 97bdecf7..ce957327 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -73,6 +73,7 @@ typedef struct { bool_t adjust_table_min_width; bool_t focus_new_tab; double font_factor; + double zoom_factor; int32_t font_max_size; int32_t font_min_size; int32_t scroll_step; diff --git a/src/prefsparser.cc b/src/prefsparser.cc index 8755890c..70cb7e68 100644 --- a/src/prefsparser.cc +++ b/src/prefsparser.cc @@ -243,7 +243,8 @@ void PrefsParser::parse(FILE *fp) { "penalty_em_dash_right_2", &prefs.penalty_em_dash_right_2, PREFS_FRACTION_100, 0 }, { "stretchability_factor", &prefs.stretchability_factor, - PREFS_FRACTION_100, 0 } + PREFS_FRACTION_100, 0 }, + { "zoom_factor", &prefs.zoom_factor, PREFS_DOUBLE, 0 } }; // changing the LC_NUMERIC locale (temporarily) to C // avoids parsing problems with float numbers diff --git a/src/styleengine.cc b/src/styleengine.cc index 77d19db3..a2cb0c66 100644 --- a/src/styleengine.cc +++ b/src/styleengine.cc @@ -60,7 +60,8 @@ void StyleImageDeletionReceiver::deleted (lout::signal::ObservedObject *object) // ---------------------------------------------------------------------- StyleEngine::StyleEngine (dw::core::Layout *layout, - const DilloUrl *pageUrl, const DilloUrl *baseUrl) { + const DilloUrl *pageUrl, const DilloUrl *baseUrl, + float zoom) { StyleAttrs style_attrs; FontAttrs font_attrs; @@ -73,13 +74,14 @@ StyleEngine::StyleEngine (dw::core::Layout *layout, this->baseUrl = baseUrl ? a_Url_dup(baseUrl) : NULL; importDepth = 0; dpmm = layout->dpiX () / 25.4; /* assume dpiX == dpiY */ + this->zoom = zoom; stackPush (); Node *n = stack->getLastRef (); /* Create a dummy font, attribute, and tag for the bottom of the stack. */ font_attrs.name = prefs.font_sans_serif; - font_attrs.size = roundInt(14 * prefs.font_factor); + font_attrs.size = roundInt(14 * prefs.font_factor * zoom); if (font_attrs.size < prefs.font_min_size) font_attrs.size = prefs.font_min_size; if (font_attrs.size > prefs.font_max_size) @@ -410,31 +412,31 @@ void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props, if (p->type == CSS_TYPE_ENUM) { switch (p->value.intVal) { case CSS_FONT_SIZE_XX_SMALL: - fontAttrs.size = roundInt(8.1 * prefs.font_factor); + fontAttrs.size = roundInt(8.1 * prefs.font_factor * zoom); break; case CSS_FONT_SIZE_X_SMALL: - fontAttrs.size = roundInt(9.7 * prefs.font_factor); + fontAttrs.size = roundInt(9.7 * prefs.font_factor * zoom); break; case CSS_FONT_SIZE_SMALL: - fontAttrs.size = roundInt(11.7 * prefs.font_factor); + fontAttrs.size = roundInt(11.7 * prefs.font_factor * zoom); break; case CSS_FONT_SIZE_MEDIUM: - fontAttrs.size = roundInt(14.0 * prefs.font_factor); + fontAttrs.size = roundInt(14.0 * prefs.font_factor * zoom); break; case CSS_FONT_SIZE_LARGE: - fontAttrs.size = roundInt(16.8 * prefs.font_factor); + fontAttrs.size = roundInt(16.8 * prefs.font_factor * zoom); break; case CSS_FONT_SIZE_X_LARGE: - fontAttrs.size = roundInt(20.2 * prefs.font_factor); + fontAttrs.size = roundInt(20.2 * prefs.font_factor * zoom); break; case CSS_FONT_SIZE_XX_LARGE: - fontAttrs.size = roundInt(24.2 * prefs.font_factor); + fontAttrs.size = roundInt(24.2 * prefs.font_factor * zoom); break; case CSS_FONT_SIZE_SMALLER: - fontAttrs.size = roundInt(fontAttrs.size * 0.83); + fontAttrs.size = roundInt(fontAttrs.size * 0.83 * zoom); break; case CSS_FONT_SIZE_LARGER: - fontAttrs.size = roundInt(fontAttrs.size * 1.2); + fontAttrs.size = roundInt(fontAttrs.size * 1.2 * zoom); break; default: assert(false); // invalid font-size enum @@ -789,15 +791,17 @@ void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props, bool StyleEngine::computeValue (int *dest, CssLength value, Font *font) { switch (CSS_LENGTH_TYPE (value)) { case CSS_LENGTH_TYPE_PX: - *dest = (int) CSS_LENGTH_VALUE (value); + *dest = (int) (CSS_LENGTH_VALUE (value) * zoom); return true; case CSS_LENGTH_TYPE_MM: - *dest = roundInt (CSS_LENGTH_VALUE (value) * dpmm); + *dest = roundInt (CSS_LENGTH_VALUE (value) * dpmm * zoom); return true; case CSS_LENGTH_TYPE_EM: + /* Doesn't need zoom as it is already applied to font->size */ *dest = roundInt (CSS_LENGTH_VALUE (value) * font->size); return true; case CSS_LENGTH_TYPE_EX: + /* Doesn't need zoom as it is already applied to font->xHeight */ *dest = roundInt (CSS_LENGTH_VALUE(value) * font->xHeight); return true; case CSS_LENGTH_TYPE_NONE: diff --git a/src/styleengine.hh b/src/styleengine.hh index db3e3b85..9a78869b 100644 --- a/src/styleengine.hh +++ b/src/styleengine.hh @@ -1,3 +1,15 @@ +/* + * File: styleengine.hh + * + * Copyright 2008-2009 Johannes Hofmann + * Copyright 2024 Rodrigo Arias Mallo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + */ + #ifndef __STYLEENGINE_HH__ #define __STYLEENGINE_HH__ @@ -37,6 +49,7 @@ class StyleEngine { Doctree *doctree; int importDepth; float dpmm; + float zoom; DilloUrl *pageUrl, *baseUrl; void stackPush (); @@ -69,7 +82,7 @@ class StyleEngine { static void init (); StyleEngine (dw::core::Layout *layout, - const DilloUrl *pageUrl, const DilloUrl *baseUrl); + const DilloUrl *pageUrl, const DilloUrl *baseUrl, float zoom); ~StyleEngine (); void parse (DilloHtml *html, DilloUrl *url, const char *buf, int buflen, diff --git a/src/ui.cc b/src/ui.cc index 9eda6f23..2f05c811 100644 --- a/src/ui.cc +++ b/src/ui.cc @@ -738,6 +738,15 @@ int UI::handle(int event) } else if (cmd == KEYS_FORWARD) { a_UIcmd_forw(a_UIcmd_get_bw_by_widget(this)); ret = 1; + } else if (cmd == KEYS_ZOOM_IN) { + a_UIcmd_zoom_in(a_UIcmd_get_bw_by_widget(this)); + ret = 1; + } else if (cmd == KEYS_ZOOM_OUT) { + a_UIcmd_zoom_out(a_UIcmd_get_bw_by_widget(this)); + ret = 1; + } else if (cmd == KEYS_ZOOM_RESET) { + a_UIcmd_zoom_reset(a_UIcmd_get_bw_by_widget(this)); + ret = 1; } else if (cmd == KEYS_BOOKMARKS) { a_UIcmd_book(a_UIcmd_get_bw_by_widget(this)); ret = 1; diff --git a/src/uicmd.cc b/src/uicmd.cc index d7822e47..d289df0c 100644 --- a/src/uicmd.cc +++ b/src/uicmd.cc @@ -576,9 +576,13 @@ BrowserWindow *a_UIcmd_browser_window_new(int ww, int wh, new_bw = UIcmd_tab_new(DilloTabs, old_ui, focus); win->show(); - if (old_bw == NULL && prefs.xpos >= 0 && prefs.ypos >= 0) { - // position the first window according to preferences - DilloTabs->window()->position(prefs.xpos, prefs.ypos); + if (old_bw == NULL) { + new_bw->zoom = prefs.zoom_factor; + + if (prefs.xpos >= 0 && prefs.ypos >= 0) { + // position the first window according to preferences + DilloTabs->window()->position(prefs.xpos, prefs.ypos); + } } win->callback(win_cb, DilloTabs); @@ -799,6 +803,8 @@ void a_UIcmd_open_url_nw(BrowserWindow *bw, const DilloUrl *url) a_UIcmd_get_wh(bw, &w, &h); new_bw = a_UIcmd_browser_window_new(w, h, 0, bw); + /* Preserve same zoom factor in new window */ + new_bw->zoom = bw->zoom; UIcmd_open_url_nbw(new_bw, url); } @@ -810,6 +816,8 @@ void a_UIcmd_open_url_nt(void *vbw, const DilloUrl *url, int focus) BrowserWindow *bw = (BrowserWindow *)vbw; BrowserWindow *new_bw = UIcmd_tab_new(BW2UI(bw)->tabs(), bw ? BW2UI(bw) : NULL, focus); + /* Preserve same zoom factor in new tab */ + new_bw->zoom = bw->zoom; UIcmd_open_url_nbw(new_bw, url); } @@ -877,6 +885,51 @@ void a_UIcmd_redirection0(void *vbw, const DilloUrl *url) a_Nav_redirection0((BrowserWindow*)vbw, url); } +/* + * Zoom in + */ +void a_UIcmd_zoom_in(void *vbw) +{ + BrowserWindow *bw = (BrowserWindow*) vbw; + bw->zoom += 0.10; + + if (bw->zoom > 10.0) + bw->zoom = 10.0; + + a_UIcmd_set_msg(bw, "Zoom set to %.0f%%", bw->zoom * 100.0); + + a_Nav_repush((BrowserWindow*)vbw); +} + +/* + * Zoom out + */ +void a_UIcmd_zoom_out(void *vbw) +{ + BrowserWindow *bw = (BrowserWindow*) vbw; + bw->zoom -= 0.10; + + if (bw->zoom < 0.10) + bw->zoom = 0.10; + + a_UIcmd_set_msg(bw, "Zoom set to %.0f%%", bw->zoom * 100.0); + + a_Nav_repush((BrowserWindow*)vbw); +} + +/* + * Zoom reset + */ +void a_UIcmd_zoom_reset(void *vbw) +{ + BrowserWindow *bw = (BrowserWindow*) vbw; + bw->zoom = 1.0; + + a_UIcmd_set_msg(bw, "Zoom set to %.0f%%", bw->zoom * 100.0); + + a_Nav_repush((BrowserWindow*)vbw); +} + /* * Return a suitable filename for a given URL path. */ diff --git a/src/uicmd.hh b/src/uicmd.hh index a1af6335..ec630d65 100644 --- a/src/uicmd.hh +++ b/src/uicmd.hh @@ -1,3 +1,15 @@ +/* + * File: uicmd.cc + * + * Copyright (C) 2005-2011 Jorge Arellano Cid + * Copyright (C) 2024 Rodrigo Arias Mallo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + */ + #ifndef __UICMD_HH__ #define __UICMD_HH__ @@ -21,6 +33,9 @@ void a_UIcmd_back_popup(void *vbw, int x, int y); void a_UIcmd_forw(void *vbw); void a_UIcmd_forw_popup(void *vbw, int x, int y); void a_UIcmd_home(void *vbw); +void a_UIcmd_zoom_in(void *vbw); +void a_UIcmd_zoom_out(void *vbw); +void a_UIcmd_zoom_reset(void *vbw); void a_UIcmd_reload(void *vbw); void a_UIcmd_repush(void *vbw); void a_UIcmd_redirection0(void *vbw, const DilloUrl *url); diff --git a/src/web.cc b/src/web.cc index 5266c6e6..6f808b02 100644 --- a/src/web.cc +++ b/src/web.cc @@ -2,6 +2,7 @@ * File: web.cc * * Copyright 2005-2007 Jorge Arellano Cid + * Copyright 2024 Rodrigo Arias Mallo * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -53,9 +54,10 @@ int a_Web_dispatch_by_type (const char *Type, DilloWeb *Web, _MSG("a_Web_dispatch_by_type\n"); - dReturn_val_if_fail(Web->bw != NULL, -1); + BrowserWindow *bw = Web->bw; + dReturn_val_if_fail(bw != NULL, -1); - Layout *layout = (Layout*)Web->bw->render_layout; + Layout *layout = (Layout*)bw->render_layout; Viewer_t viewer = a_Mime_get_viewer(Type); if (viewer == NULL) @@ -73,7 +75,7 @@ int a_Web_dispatch_by_type (const char *Type, DilloWeb *Web, style::createPerLength (0)); /* Set a style for the widget */ - StyleEngine styleEngine (layout, Web->url, Web->url); + StyleEngine styleEngine (layout, Web->url, Web->url, bw->zoom); styleEngine.startElement ("body", Web->bw); dw = (Widget*) viewer(Type, Web, Call, Data); -- cgit v1.2.3