Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make highlights respect word selection mode #742

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
4 changes: 2 additions & 2 deletions pdf_viewer/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ extern bool FORCE_CUSTOM_LINE_ALGORITHM;
extern float OVERVIEW_SIZE[2];
extern float OVERVIEW_OFFSET[2];
extern bool IGNORE_WHITESPACE_IN_PRESENTATION_MODE;
extern bool EXACT_HIGHLIGHT_SELECT;
extern bool LEGACY_WORD_SELECT;
extern bool SHOW_DOC_PATH;
extern float FASTREAD_OPACITY;
extern bool SHOULD_WARN_ABOUT_USER_KEY_OVERRIDE;
Expand Down Expand Up @@ -397,7 +397,7 @@ ConfigManager::ConfigManager(const Path& default_path, const Path& auto_path ,co
configs.push_back({ L"overview_size", &OVERVIEW_SIZE, fvec2_serializer, fvec2_deserializer, nullptr });
configs.push_back({ L"overview_offset", &OVERVIEW_OFFSET, fvec2_serializer, fvec2_deserializer, nullptr });
configs.push_back({ L"ignore_whitespace_in_presentation_mode", &IGNORE_WHITESPACE_IN_PRESENTATION_MODE, bool_serializer, bool_deserializer, bool_validator });
configs.push_back({ L"exact_highlight_select", &EXACT_HIGHLIGHT_SELECT, bool_serializer, bool_deserializer, bool_validator });
configs.push_back({ L"legacy_word_select", &LEGACY_WORD_SELECT, bool_serializer, bool_deserializer, bool_validator });
configs.push_back({ L"show_doc_path", &SHOW_DOC_PATH, bool_serializer, bool_deserializer, bool_validator });
configs.push_back({ L"fastread_opacity", &FASTREAD_OPACITY, float_serializer, float_deserializer, nullptr });
configs.push_back({ L"should_warn_about_user_key_override", &SHOULD_WARN_ABOUT_USER_KEY_OVERRIDE, bool_serializer, bool_deserializer, bool_validator });
Expand Down
5 changes: 3 additions & 2 deletions pdf_viewer/document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ extern bool CREATE_TABLE_OF_CONTENTS_IF_NOT_EXISTS;
extern int MAX_CREATED_TABLE_OF_CONTENTS_SIZE;
extern bool FORCE_CUSTOM_LINE_ALGORITHM;
extern bool SUPER_FAST_SEARCH;
extern bool LEGACY_WORD_SELECT;


int Document::get_mark_index(char symbol) {
Expand Down Expand Up @@ -80,7 +81,7 @@ void Document::fill_highlight_rects(fz_context* ctx, fz_document* doc_) {
std::vector<fz_rect> highlight_rects;
std::vector<fz_rect> merged_rects;
std::wstring highlight_text;
get_text_selection(ctx, highlight.selection_begin, highlight.selection_end, true, highlight_rects, highlight_text, doc_);
get_text_selection(ctx, highlight.selection_begin, highlight.selection_end, LEGACY_WORD_SELECT, highlight_rects, highlight_text, doc_);
merge_selected_character_rects(highlight_rects, merged_rects);

if (i < highlights.size()) {
Expand Down Expand Up @@ -1533,7 +1534,7 @@ void Document::embed_annotations(std::wstring new_file_path) {
std::vector<fz_rect> selected_characters_page_rects;
std::wstring selected_text;

get_text_selection(highlight.selection_begin, highlight.selection_end, true, selected_characters, selected_text);
get_text_selection(highlight.selection_begin, highlight.selection_end, LEGACY_WORD_SELECT, selected_characters, selected_text);
merge_selected_character_rects(selected_characters, merged_characters);

for (auto absrect : merged_characters) {
Expand Down
24 changes: 20 additions & 4 deletions pdf_viewer/document_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ extern float MOVE_SCREEN_PERCENTAGE;
extern float FIT_TO_PAGE_WIDTH_RATIO;
extern float RULER_PADDING;
extern float RULER_X_PADDING;
extern bool EXACT_HIGHLIGHT_SELECT;
extern bool IGNORE_STATUSBAR_IN_PRESENTATION_MODE;


Expand Down Expand Up @@ -199,6 +198,21 @@ void DocumentView::delete_closest_bookmark_to_offset(float offset) {
current_document->delete_closest_bookmark(offset);
}

void DocumentView::expand_highlight_with_index(int index) {
Highlight hl = get_highlight_with_index(index);
delete_highlight_with_index(index);
add_highlight(hl.selection_begin, hl.selection_end, true, hl.type);
}

void DocumentView::expand_all_highlights() {
std::size_t num_highlights = current_document->get_highlights().size();
if (num_highlights > 0) {
for (; num_highlights--;) {
expand_highlight_with_index(0);
}
}
}

float DocumentView::get_offset_x() {
return offset_x;
}
Expand Down Expand Up @@ -298,17 +312,19 @@ void DocumentView::add_bookmark(std::wstring desc) {
}
}

void DocumentView::add_highlight(AbsoluteDocumentPos selection_begin, AbsoluteDocumentPos selection_end, char type) {
void DocumentView::add_highlight(AbsoluteDocumentPos selection_begin, AbsoluteDocumentPos selection_end, bool is_word_selection, char type) {

if (current_document) {
std::vector<fz_rect> selected_characters;
std::vector<fz_rect> merged_characters;
std::wstring selected_text;

get_text_selection(selection_begin, selection_end, !EXACT_HIGHLIGHT_SELECT, selected_characters, selected_text);
get_text_selection(selection_begin, selection_end, is_word_selection, selected_characters, selected_text);
merge_selected_character_rects(selected_characters, merged_characters);
if (selected_text.size() > 0) {
current_document->add_highlight(selected_text, merged_characters, selection_begin, selection_end, type);
const fz_point center_begin = rect_get_center(selected_characters.front());
const fz_point center_end = rect_get_center(selected_characters.back());
current_document->add_highlight(selected_text, merged_characters, { center_begin.x, center_begin.y }, { center_end.x, center_end.y }, type);
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion pdf_viewer/document_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ class DocumentView {
void delete_highlight_with_index(int index);
void delete_highlight(Highlight hl);
void delete_closest_bookmark_to_offset(float offset);
void expand_highlight_with_index(int index);
void expand_all_highlights();
float get_offset_x();
float get_offset_y();
AbsoluteDocumentPos get_offsets();
Expand All @@ -91,7 +93,7 @@ class DocumentView {
void get_text_selection(AbsoluteDocumentPos selection_begin, AbsoluteDocumentPos selection_end, bool is_word_selection, std::vector<fz_rect>& selected_characters, std::wstring& text_selection);
void add_mark(char symbol);
void add_bookmark(std::wstring desc);
void add_highlight(AbsoluteDocumentPos selection_begin, AbsoluteDocumentPos selection_end, char type);
void add_highlight(AbsoluteDocumentPos selection_begin, AbsoluteDocumentPos selection_end, bool is_word_selection, char type);
void on_view_size_change(int new_width, int new_height);
void absolute_to_window_pos(float absolute_x, float absolute_y, float* window_x, float* window_y);
//void absolute_to_window_pos_pixels(float absolute_x, float absolute_y, float* window_x, float* window_y);
Expand Down
28 changes: 27 additions & 1 deletion pdf_viewer/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,30 @@ class DeleteHighlightCommand : public Command {
}
};

class ExpandHighlightCommand : public Command {
void perform(MainWidget* widget) {
if (widget->selected_highlight_index != -1) {
widget->main_document_view->expand_highlight_with_index(widget->selected_highlight_index);
}
widget->validate_render();
}

std::string get_name() {
return "expand_highlight";
}
};

class ExpandAllHighlightsCommand : public Command {
void perform(MainWidget* widget) {
widget->main_document_view->expand_all_highlights();
widget->validate_render();
}

std::string get_name() {
return "expand_all_highlights";
}
};

class GotoPortalCommand : public Command {
void perform(MainWidget* widget) {
std::optional<Portal> link = widget->main_document_view->find_closest_portal();
Expand Down Expand Up @@ -1530,7 +1554,7 @@ class SetSelectHighlightTypeCommand : public SymbolCommand {
class AddHighlightWithCurrentTypeCommand : public Command {
void perform(MainWidget* widget) {
if (widget->main_document_view->selected_character_rects.size() > 0) {
widget->main_document_view->add_highlight(widget->selection_begin, widget->selection_end, widget->select_highlight_type);
widget->main_document_view->add_highlight(widget->selection_begin, widget->selection_end, widget->is_word_selection, widget->select_highlight_type);
widget->main_document_view->selected_character_rects.clear();
widget->selected_text.clear();
}
Expand Down Expand Up @@ -2225,6 +2249,8 @@ CommandManager::CommandManager(ConfigManager* config_manager) {
new_commands["delete_portal"] = []() {return std::make_unique< DeletePortalCommand>(); };
new_commands["delete_bookmark"] = []() {return std::make_unique< DeleteBookmarkCommand>(); };
new_commands["delete_highlight"] = []() {return std::make_unique< DeleteHighlightCommand>(); };
new_commands["expand_highlight"] = []() {return std::make_unique< ExpandHighlightCommand>(); };
new_commands["expand_all_highlights"] = []() {return std::make_unique< ExpandAllHighlightsCommand>(); };
new_commands["goto_link"] = []() {return std::make_unique< GotoPortalCommand>(); };
new_commands["goto_portal"] = []() {return std::make_unique< GotoPortalCommand>(); };
new_commands["edit_link"] = []() {return std::make_unique< EditPortalCommand>(); };
Expand Down
2 changes: 2 additions & 0 deletions pdf_viewer/keys.config
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ goto_highlight gh
goto_highlight_g gH
# Left click on a highlight and then press the `delete_highlight` shortcut to delete it.
delete_highlight dh
# Left click on a highlight and then press the `expand_highlight` shortcut to expand it to its word boundaries
expand_highlight eh

# Sets the highlight type to be used for other operations (the default highlight type is 'a')
#set_select_highlight_type
Expand Down
2 changes: 1 addition & 1 deletion pdf_viewer/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@ bool FORCE_CUSTOM_LINE_ALGORITHM = false;
float OVERVIEW_SIZE[2] = { 0.8f, 0.4f };
float OVERVIEW_OFFSET[2] = { 0.0f, 0.0f };
bool IGNORE_WHITESPACE_IN_PRESENTATION_MODE = false;
bool EXACT_HIGHLIGHT_SELECT = false;
bool SHOW_DOC_PATH = false;
float FASTREAD_OPACITY = 0.5f;
bool SHOULD_WARN_ABOUT_USER_KEY_OVERRIDE = true;
Expand All @@ -215,6 +214,7 @@ float HYPERDRIVE_SPEED_FACTOR = 10.0f;
float SMOOTH_SCROLL_SPEED = 3.0f;
float SMOOTH_SCROLL_DRAG = 3000.0f;
int PRERENDERED_PAGE_COUNT = 0;
bool LEGACY_WORD_SELECT = false;

float PAGE_SEPARATOR_WIDTH = 0.0f;
float PAGE_SEPARATOR_COLOR[3] = {0.9f, 0.9f, 0.9f};
Expand Down
17 changes: 8 additions & 9 deletions pdf_viewer/main_widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ void MainWidget::mouseMoveEvent(QMouseEvent* mouse_event) {

main_document_view->get_text_selection(selection_begin,
selection_end,
is_word_selecting,
is_word_selection,
main_document_view->selected_character_rects,
selected_text);

Expand Down Expand Up @@ -1409,7 +1409,7 @@ void MainWidget::handle_left_click(WindowPos click_pos, bool down, bool is_shift
if (!mouse_drag_mode) {
is_selecting = true;
if (SINGLE_CLICK_SELECTS_WORDS) {
is_word_selecting = true;
is_word_selection = true;
}
}
else {
Expand Down Expand Up @@ -1438,10 +1438,9 @@ void MainWidget::handle_left_click(WindowPos click_pos, bool down, bool is_shift

main_document_view->get_text_selection(last_mouse_down,
abs_doc_pos,
is_word_selecting,
is_word_selection,
main_document_view->selected_character_rects,
selected_text);
is_word_selecting = false;
}
else {
handle_click(click_pos);
Expand Down Expand Up @@ -1657,7 +1656,7 @@ void MainWidget::mouseReleaseEvent(QMouseEvent* mevent) {
else {
handle_left_click({ mevent->pos().x(), mevent->pos().y() }, false, is_shift_pressed, is_control_pressed, is_alt_pressed);
if (is_select_highlight_mode && (main_document_view->selected_character_rects.size() > 0)) {
main_document_view->add_highlight(selection_begin, selection_end, select_highlight_type);
main_document_view->add_highlight(selection_begin, selection_end, is_word_selection, select_highlight_type);
clear_selected_text();
}
if (main_document_view->selected_character_rects.size() > 0) {
Expand Down Expand Up @@ -1703,10 +1702,10 @@ void MainWidget::mouseDoubleClickEvent(QMouseEvent* mevent) {
if (mevent->button() == Qt::MouseButton::LeftButton) {
is_selecting = true;
if (SINGLE_CLICK_SELECTS_WORDS) {
is_word_selecting = false;
is_word_selection = false;
}
else {
is_word_selecting = true;
is_word_selection = true;
}
}
}
Expand Down Expand Up @@ -3678,14 +3677,14 @@ void MainWidget::handle_goto_bookmark_global() {

void MainWidget::handle_add_highlight(char symbol) {
if (main_document_view->selected_character_rects.size() > 0) {
main_document_view->add_highlight(selection_begin, selection_end, symbol);
main_document_view->add_highlight(selection_begin, selection_end, is_word_selection, symbol);
main_document_view->selected_character_rects.clear();
selected_text.clear();
}
else if (selected_highlight_index != -1) {
Highlight new_highlight = main_document_view->get_highlight_with_index(selected_highlight_index);
main_document_view->delete_highlight_with_index(selected_highlight_index);
main_document_view->add_highlight(new_highlight.selection_begin, new_highlight.selection_end, symbol);
main_document_view->add_highlight(new_highlight.selection_begin, new_highlight.selection_end, is_word_selection, symbol);
selected_highlight_index = -1;
}
}
Expand Down
2 changes: 1 addition & 1 deletion pdf_viewer/main_widget.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class MainWidget : public QWidget, ConfigFileChangeListener{
// is the user currently selecing text? (happens when we left click and move the cursor)
bool is_selecting = false;
// is the user in word select mode? (happens when we double left click and move the cursor)
bool is_word_selecting = false;
bool is_word_selection = false;
std::wstring selected_text;

bool is_select_highlight_mode = false;
Expand Down
3 changes: 3 additions & 0 deletions pdf_viewer/prefs.config
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
# (can be 0 or 1) if set, shows a notification on startup if a new version of sioyek is available
check_for_updates_on_startup 0

# Force word selection mode for highlights read from database or when embedding into PDF files
legacy_word_select 0

# Use old keybind parsing method (only for backwards compatibility)
use_legacy_keybinds 0

Expand Down
7 changes: 6 additions & 1 deletion pdf_viewer/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ void rect_to_quad(fz_rect rect, float quad[8]) {
quad[7] = rect.y1;
}

fz_point rect_get_center(const fz_rect& rect) {
return { (rect.x0 + rect.x1) / 2, (rect.y0 + rect.y1) / 2 };
}

void copy_to_clipboard(const std::wstring& text, bool selection) {
auto clipboard = QGuiApplication::clipboard();
auto qtext = QString::fromStdWString(text);
Expand Down Expand Up @@ -600,7 +604,8 @@ fz_stext_char* find_closest_char_to_document_point(const std::vector<fz_stext_ch
int index = 0;
for (auto current_char : flat_chars) {

fz_point quad_center = current_char->origin;
// This works better than current_char->origin
const fz_point quad_center = rect_get_center(fz_rect_from_quad(current_char->quad));
float distance = dist_squared(document_point, quad_center);
if (distance < min_distance) {
min_distance = distance;
Expand Down
1 change: 1 addition & 0 deletions pdf_viewer/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ int argminf(const std::vector<T> &collection, std::function<float(T)> f) {
return min_index;
}
void rect_to_quad(fz_rect rect, float quad[8]);
fz_point rect_get_center(const fz_rect& rect);
void copy_to_clipboard(const std::wstring& text, bool selection=false);
void install_app(const char* argv0);
int get_f_key(std::wstring name);
Expand Down
12 changes: 6 additions & 6 deletions resources/sioyek.1
Original file line number Diff line number Diff line change
Expand Up @@ -1263,12 +1263,6 @@ Offset of the overview window as floats from the center of the page.

Always use fit_to_page_smart (ignoring whitespace) in presentation view.
.HP
.B exact_highlight_select
.I boolean

If set to 0, then in word select mode, select the whole word even if
the cursor is only partially on the word. If set to 1, then select the word only if the range of the cursor's selection fully includes the word.
.HP
.B show_doc_path
.I boolean

Expand Down Expand Up @@ -1312,6 +1306,12 @@ always attempted.
If set to 0, search is performed by the mupdf backend. If set to 1, a super
fast search index is used instead. This leads to a slight increase in memory.
.HP
.B legacy_word_select
.I boolean

If set to 1, highlights are expanded to entail entire words when read from the
database or when embedded into PDF files.
.HP
.B case_sensitive_search
.I boolean

Expand Down