From 9ba59929c23c71a5231670a50c3fcb1165111c90 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 22 Mar 2021 10:40:21 +0100 Subject: Fix touch scroll clamping to selected item, making it appear laggy. Fix emoji offset for non 1.0 scaling --- include/Body.hpp | 13 ++-- include/Entry.hpp | 1 + include/SearchBar.hpp | 1 + include/Utils.hpp | 3 + src/Body.cpp | 173 +++++++++++++++++++++++++++++--------------------- src/Entry.cpp | 21 +++++- src/QuickMedia.cpp | 56 ++++++++++------ src/SearchBar.cpp | 15 +++++ src/Text.cpp | 2 +- src/Utils.cpp | 30 +++++++++ 10 files changed, 215 insertions(+), 100 deletions(-) diff --git a/include/Body.hpp b/include/Body.hpp index 869ce0b..53622e8 100644 --- a/include/Body.hpp +++ b/include/Body.hpp @@ -176,10 +176,10 @@ namespace QuickMedia { bool select_next_page(); // Select previous item, ignoring invisible items. Returns true if the item was changed or if the item scrolled. This can be used to check if the top was hit when wrap_around is set to false - bool select_previous_item(bool scroll_page_if_large_item = true); + bool select_previous_item(bool scroll_page_if_large_item = true, bool reset_select_scroll = true); // Select next item, ignoring invisible items. Returns true if the item was changed or if the item scrolled. This can be used to check if the bottom was hit when wrap_around is set to false - bool select_next_item(bool scroll_page_if_large_item = true); + bool select_next_item(bool scroll_page_if_large_item = true, bool reset_select_scroll = true); void set_selected_item(int item, bool reset_prev_selected_item = true); void reset_prev_selected_item(); @@ -214,7 +214,7 @@ namespace QuickMedia { // This happens because of |draw| sets thumbnails as unreferenced at the beginning and cleans them up at the end if they are not drawn in the same function call. // TODO: Right now drawing an item that also exists in the body will cause the text to update geometry every frame if the text is wrapping text and the items are drawn at different sizes, // because of Text::setMaxWidth - void draw_item(sf::RenderWindow &window, BodyItem *item, sf::Vector2f pos, sf::Vector2f size, bool include_embedded_item = true); + void draw_item(sf::RenderWindow &window, BodyItem *item, sf::Vector2f pos, sf::Vector2f size, bool include_embedded_item = true, bool is_embedded = false); float get_item_height(BodyItem *item, float width, bool load_texture = true, bool include_embedded_item = true); float get_spacing_y() const; @@ -232,7 +232,7 @@ namespace QuickMedia { int get_selected_item() const { return selected_item; } bool is_selected_item_last_visible_item() const; - void set_page_scroll(float scroll) { page_scroll = scroll; } + void set_page_scroll(float scroll); float get_page_scroll() const { return page_scroll; } // This is the item we can see the end of bool is_last_item_fully_visible() const { return last_item_fully_visible; } @@ -270,6 +270,7 @@ namespace QuickMedia { sf::Sprite image; sf::Sprite loading_icon; int num_visible_items; + bool first_item_fully_visible; bool last_item_fully_visible; int first_fully_visible_item; int last_fully_visible_item; @@ -281,10 +282,10 @@ namespace QuickMedia { bool items_cut_off = false; float offset_to_top = 0.0f; float offset_to_bottom = 0.0f; - bool experimental_use_touch = false; - bool mouse_state_set = false; + int clamp_selected_item_to_body_count = 1; bool mouse_left_pressed = false; bool mouse_left_clicked = false; + bool has_scrolled_with_input = false; sf::Vector2f mouse_click_pos; sf::Vector2f mouse_release_pos; double mouse_press_pixels_moved_abs; diff --git a/include/Entry.hpp b/include/Entry.hpp index 32dcda2..10210f8 100644 --- a/include/Entry.hpp +++ b/include/Entry.hpp @@ -37,5 +37,6 @@ namespace QuickMedia { float width; sf::RoundedRectangleShape background; sf::Text placeholder; + bool mouse_left_inside; }; } \ No newline at end of file diff --git a/include/SearchBar.hpp b/include/SearchBar.hpp index 4c9757c..b2cdf4d 100644 --- a/include/SearchBar.hpp +++ b/include/SearchBar.hpp @@ -67,6 +67,7 @@ namespace QuickMedia { bool input_masked; bool typing; bool backspace_pressed; + bool mouse_left_inside; float vertical_pos; sf::Clock time_since_search_update; }; diff --git a/include/Utils.hpp b/include/Utils.hpp index 7ca409c..c1448f4 100644 --- a/include/Utils.hpp +++ b/include/Utils.hpp @@ -2,4 +2,7 @@ namespace QuickMedia { float get_ui_scale(); + void show_virtual_keyboard(); + void hide_virtual_keyboard(); + bool is_touch_enabled(); } \ No newline at end of file diff --git a/src/Body.cpp b/src/Body.cpp index 667232e..a34fb7d 100644 --- a/src/Body.cpp +++ b/src/Body.cpp @@ -136,10 +136,6 @@ namespace QuickMedia { item_background.setFillColor(sf::Color(55, 60, 68)); sf::Vector2f loading_icon_size(loading_icon.getTexture()->getSize().x, loading_icon.getTexture()->getSize().y); loading_icon.setOrigin(loading_icon_size.x * 0.5f, loading_icon_size.y * 0.5f); - const char *qm_enable_touch = getenv("QM_ENABLE_TOUCH"); - if(qm_enable_touch && qm_enable_touch[0] == '1') { - experimental_use_touch = true; - } } // TODO: Make this work with wraparound enabled? @@ -168,10 +164,12 @@ namespace QuickMedia { return true; } - bool Body::select_previous_item(bool scroll_page_if_large_item) { + bool Body::select_previous_item(bool scroll_page_if_large_item, bool reset_select_scroll) { if(items.empty()) return false; + clamp_selected_item_to_body_count = 1; + if(scroll_page_if_large_item && !selected_line_top_visible) { page_scroll += 128.0f; return true; @@ -195,18 +193,22 @@ namespace QuickMedia { break; } - // selected_scrolled = 0.0f; + if(reset_select_scroll) + selected_scrolled = 0.0f; if(selected_item == new_selected_item) return false; + selected_item = new_selected_item; return true; } - bool Body::select_next_item(bool scroll_page_if_large_item) { + bool Body::select_next_item(bool scroll_page_if_large_item, bool reset_select_scroll) { if(items.empty()) return false; + clamp_selected_item_to_body_count = 1; + if(scroll_page_if_large_item && !selected_line_bottom_visible) { page_scroll -= 128.0f; return true; @@ -230,10 +232,12 @@ namespace QuickMedia { break; } - //selected_scrolled = 0.0f; + if(reset_select_scroll) + selected_scrolled = 0.0f; if(selected_item == new_selected_item) return false; + selected_item = new_selected_item; return true; } @@ -246,6 +250,7 @@ namespace QuickMedia { if(reset_prev_selected_item) prev_selected_item = selected_item; clamp_selection(); + clamp_selected_item_to_body_count = 1; //page_scroll = 0.0f; } @@ -262,22 +267,22 @@ namespace QuickMedia { } void Body::select_first_item() { - if(selected_item != 0) - selected_scrolled = 0.0f; + selected_scrolled = 0.0f; selected_item = 0; prev_selected_item = selected_item; page_scroll = 0.0f; clamp_selection(); + clamp_selected_item_to_body_count = 1; } void Body::select_last_item() { int new_selected_item = std::max(0, (int)items.size() - 1); - if(selected_item != new_selected_item) - selected_scrolled = 0.0f; + selected_scrolled = 0.0f; selected_item = new_selected_item; //prev_selected_item = selected_item; //page_scroll = 0.0f; clamp_selection(); + clamp_selected_item_to_body_count = 1; } void Body::clear_items() { @@ -287,6 +292,7 @@ namespace QuickMedia { selected_item = 0; prev_selected_item = selected_item; page_scroll = 0.0f; + clamp_selected_item_to_body_count = 1; } void Body::prepend_items(BodyItems new_items) { @@ -376,25 +382,11 @@ namespace QuickMedia { } bool Body::on_event(const sf::RenderWindow &window, const sf::Event &event) { - if(!experimental_use_touch) - return false; + if(event.type == sf::Event::Resized) + clamp_selected_item_to_body_count = 1; - if(!mouse_state_set) { - mouse_state_set = true; - mouse_left_pressed = sf::Mouse::isButtonPressed(sf::Mouse::Left); - if(sf::Mouse::isButtonPressed(sf::Mouse::Left)) { - auto mpos = sf::Mouse::getPosition(window); - if(sf::FloatRect(body_pos, body_size).contains(sf::Vector2f(mpos.x, mpos.y))) { - mouse_left_pressed = true; - mouse_pos_raw = sf::Mouse::getPosition(window); - mouse_pos = sf::Vector2f(mouse_pos_raw.x, mouse_pos_raw.y); - prev_mouse_pos = mouse_pos; - mouse_click_pos = mouse_pos; - mouse_press_pixels_moved_abs = 0.0; - return true; - } - } - } + if(!is_touch_enabled()) + return false; if(event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left && !mouse_left_pressed && sf::FloatRect(body_pos, body_size).contains(sf::Vector2f(event.mouseButton.x, event.mouseButton.y))) { mouse_left_pressed = true; @@ -404,6 +396,7 @@ namespace QuickMedia { prev_mouse_pos = mouse_pos; mouse_click_pos = mouse_pos; mouse_press_pixels_moved_abs = 0.0; + has_scrolled_with_input = true; return true; } else if(event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Left && mouse_left_pressed) { mouse_left_pressed = false; @@ -437,7 +430,14 @@ namespace QuickMedia { elapsed_time_sec = draw_timer.getElapsedTime().asSeconds(); - if(experimental_use_touch) { + bool keep_selected_inside_body = clamp_selected_item_to_body_count > 0 || offset_to_top > 0.1f || offset_to_bottom > 0.1f; + if(has_scrolled_with_input) { + clamp_selected_item_to_body_count--; + if(clamp_selected_item_to_body_count < 0) + clamp_selected_item_to_body_count = 0; + } + + if(is_touch_enabled()) { float frame_time = frame_timer.restart().asSeconds(); if(frame_time > 2.0f) frame_time = 2.0f; @@ -461,6 +461,20 @@ namespace QuickMedia { } } + if(mouse_scroll_accel.y > 0.1 && first_fully_visible_item == -1) { + keep_selected_inside_body = true; + } else if(mouse_scroll_accel.y < -0.1 && last_fully_visible_item == -1) { + keep_selected_inside_body = true; + } + + if(mouse_scroll_accel.y > 0.1 && first_fully_visible_item != -1) { + selected_item = first_fully_visible_item; + clamp_selection(); + } else if(mouse_scroll_accel.y < -0.1 && last_fully_visible_item != -1) { + selected_item = last_fully_visible_item; + clamp_selection(); + } + if(!mouse_left_pressed) { const float scroll_deaccel = 1.02f; double deaccel = scroll_deaccel * (1.0 + frame_time); @@ -475,21 +489,8 @@ namespace QuickMedia { if(fabs(mouse_scroll_accel.y) < 0.0001) mouse_scroll_accel.y = 0.0; } - - if(selected_item != -1) { - if(selected_scrolled <= -selected_item_height) { - selected_scrolled += selected_item_height; - select_next_item(false); - } else if(selected_scrolled >= selected_item_height) { - selected_scrolled -= selected_item_height; - select_previous_item(false); - } - } } - //item_background.setFillColor(front_color); - //item_background.setOutlineThickness(1.0f); - //item_background.setOutlineColor(sf::Color(13, 15, 17)); item_separator.setFillColor(line_separator_color); num_visible_items = 0; first_fully_visible_item = -1; @@ -505,6 +506,7 @@ namespace QuickMedia { if(body_item->embedded_item) clear_body_item_cache(body_item->embedded_item.get()); } + first_item_fully_visible = true; last_item_fully_visible = true; items_cut_off = false; offset_to_top = 0.0f; @@ -558,37 +560,42 @@ namespace QuickMedia { selected_line_top_visible = pos.y - start_y + page_scroll >= 0.0f; selected_line_bottom_visible = pos.y - start_y + page_scroll + selected_item_height <= size.y; - if(pos.y - start_y + page_scroll >= size.y && !selected_item_fits_on_screen) - page_scroll = 0.0f; - else if(pos.y - start_y + page_scroll + selected_item_height <= 0.0f && !selected_item_fits_on_screen) - page_scroll = size.y - selected_item_height; + if(keep_selected_inside_body) { + if(pos.y - start_y + page_scroll >= size.y && !selected_item_fits_on_screen) + page_scroll = 0.0f; + else if(pos.y - start_y + page_scroll + selected_item_height <= 0.0f && !selected_item_fits_on_screen) + page_scroll = size.y - selected_item_height; + } selected_line_top_visible |= selected_item_fits_on_screen; selected_line_bottom_visible |= selected_item_fits_on_screen; - if(items_cut_off) { - if(offset_to_top > 0.0f) - page_scroll -= offset_to_top; - else if(offset_to_bottom > 0.0f) - page_scroll += offset_to_bottom; - } else { - if(attach_side == AttachSide::TOP) - page_scroll -= offset_to_top; - else if(attach_side == AttachSide::BOTTOM) - page_scroll += offset_to_bottom; - } + if(keep_selected_inside_body) { + if(items_cut_off) { + if(offset_to_top > 0.0f) + page_scroll -= offset_to_top; + else if(offset_to_bottom > 0.0f) + page_scroll += offset_to_bottom; + } else { + if(attach_side == AttachSide::TOP) + page_scroll -= offset_to_top; + else if(attach_side == AttachSide::BOTTOM) + page_scroll += offset_to_bottom; + } - if(page_scroll > size.y - selected_item_height && selected_item_fits_on_screen) { - //fprintf(stderr, "top!\n"); - page_scroll = size.y - selected_item_height; - } else if(page_scroll < 0.0f && selected_line_top_visible && selected_item_fits_on_screen) { - //fprintf(stderr, "bottom!\n"); - page_scroll = 0.0f; + if(page_scroll > size.y - selected_item_height && selected_item_fits_on_screen) { + //fprintf(stderr, "top!\n"); + page_scroll = size.y - selected_item_height; + } else if(page_scroll < 0.0f && selected_line_top_visible && selected_item_fits_on_screen) { + //fprintf(stderr, "bottom!\n"); + page_scroll = 0.0f; + } } - page_scroll = std::floor(page_scroll); + //page_scroll = std::floor(page_scroll); pos.y += page_scroll; + bool first_item_fully_visible = true; bool last_item_fully_visible_set = false; bool items_cut_off_set = false; @@ -610,6 +617,7 @@ namespace QuickMedia { if(prev_pos.y < start_y) { items_cut_off = true; items_cut_off_set = true; + first_item_fully_visible = false; } if(prev_pos.y + item_height + spacing_y <= start_y) @@ -621,7 +629,9 @@ namespace QuickMedia { draw_item(window, item.get(), prev_pos, size, item_height, i, content_progress); glDisable(GL_SCISSOR_TEST); ++num_visible_items; - first_fully_visible_item = i; + + if(first_item_fully_visible) + first_fully_visible_item = i; } offset_to_top = prev_pos.y - start_y; @@ -634,10 +644,14 @@ namespace QuickMedia { if(!item->visible) continue; - if(after_pos.y < start_y) + if(after_pos.y < start_y) { items_cut_off = true; + first_item_fully_visible = false; + } if(after_pos.y - start_y >= size.y) { + if(first_fully_visible_item == -1) + first_item_fully_visible = false; last_item_fully_visible = false; items_cut_off = true; last_item_fully_visible_set = true; @@ -664,6 +678,9 @@ namespace QuickMedia { } else { last_fully_visible_item = i; } + + if(first_item_fully_visible && first_fully_visible_item == -1) + first_fully_visible_item = i; } if(first_fully_visible_item == -1) @@ -795,15 +812,19 @@ namespace QuickMedia { return sf::Vector2f(vec.x, vec.y); } - void Body::draw_item(sf::RenderWindow &window, BodyItem *item, sf::Vector2f pos, sf::Vector2f size, bool include_embedded_item) { + void Body::draw_item(sf::RenderWindow &window, BodyItem *item, sf::Vector2f pos, sf::Vector2f size, bool include_embedded_item, bool is_embedded) { update_dirty_state(item, size.x); item->last_drawn_time = draw_timer.getElapsedTime().asMilliseconds(); sf::Vector2u window_size = window.getSize(); get_item_height(item, size.x, true, false); - glEnable(GL_SCISSOR_TEST); - glScissor(pos.x, (int)window_size.y - (int)pos.y - (int)size.y, size.x, size.y); + if(!is_embedded) { + glEnable(GL_SCISSOR_TEST); + glScissor(pos.x, (int)window_size.y - (int)pos.y - (int)size.y, size.x, size.y); + } draw_item(window, item, pos, size, size.y + spacing_y, -1, Json::Value::nullSingleton(), include_embedded_item); - glDisable(GL_SCISSOR_TEST); + if(!is_embedded) { + glDisable(GL_SCISSOR_TEST); + } } // TODO: Better message? maybe fallback to the reply message, or message status (such as message redacted) @@ -958,7 +979,7 @@ namespace QuickMedia { if(item->embedded_item) { sf::Vector2f embedded_item_pos(std::floor(item_pos.x + text_offset_x + border_width + padding_x), std::floor(item_pos.y + embedded_item_padding_y + 4.0f)); sf::Vector2f embedded_item_size(embedded_item_width, embedded_item_height); - draw_item(window, item->embedded_item.get(), embedded_item_pos, embedded_item_size, false); + draw_item(window, item->embedded_item.get(), embedded_item_pos, embedded_item_size, false, true); } else { embedded_item_load_text.setString(embedded_item_status_to_string(item->embedded_item_status)); embedded_item_load_text.setPosition(std::floor(item_pos.x + text_offset_x + border_width + padding_x), std::floor(item_pos.y + embedded_item_height * 0.5f - (embedded_item_font_size + 5.0f) * 0.5f + 4.0f)); @@ -1178,4 +1199,10 @@ namespace QuickMedia { } return true; } + + void Body::set_page_scroll(float scroll) { + selected_scrolled = 0.0f; + page_scroll = scroll; + clamp_selected_item_to_body_count = 1; + } } diff --git a/src/Entry.cpp b/src/Entry.cpp index fdd7225..5a6110c 100644 --- a/src/Entry.cpp +++ b/src/Entry.cpp @@ -17,7 +17,8 @@ namespace QuickMedia { text("", false, std::floor(16 * get_ui_scale()), 0.0f), width(0.0f), background(sf::Vector2f(1.0f, 1.0f), 7.0f, 10), - placeholder(placeholder_text, *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(16 * get_ui_scale())) + placeholder(placeholder_text, *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(16 * get_ui_scale())), + mouse_left_inside(false) { text.setEditable(true); background.setFillColor(sf::Color(55, 60, 68)); @@ -25,7 +26,24 @@ namespace QuickMedia { } void Entry::process_event(sf::Event &event) { + if(is_touch_enabled() && event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left) { + sf::FloatRect box(background.getPosition(), background.getSize()); + if(box.contains(event.mouseButton.x, event.mouseButton.y)) + mouse_left_inside = true; + else + mouse_left_inside = false; + } else if(is_touch_enabled() && event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Left) { + sf::FloatRect box(background.getPosition(), background.getSize()); + if(mouse_left_inside && box.contains(event.mouseButton.x, event.mouseButton.y)) + show_virtual_keyboard(); + mouse_left_inside = false; + } + + if(!text.isEditable()) + return; + text.processEvent(event); + if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Enter && !event.key.shift) { if(on_submit_callback) { auto u8 = text.getString().toUtf8(); @@ -43,6 +61,7 @@ namespace QuickMedia { background.setSize(sf::Vector2f(width, get_height())); if(draw_background) window.draw(background); + if(text.getString().isEmpty() && !text.isEditable()) { window.draw(placeholder); //sf::Vector2f placeholder_pos = placeholder.getPosition(); diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 61b2d1b..03f1e0d 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -1146,6 +1146,8 @@ namespace QuickMedia { tab.body->clear_cache(); } + hide_virtual_keyboard(); + if(new_tabs.size() == 1 && new_tabs[0].page->get_type() == PageTypez::MANGA_IMAGES) { select_episode(selected_item, false); Body *chapters_body = tabs[selected_tab].body.get(); @@ -1189,15 +1191,19 @@ namespace QuickMedia { body_set_selected_item(tabs[selected_tab].body.get(), selected_item); current_page = PageType::CHAT; current_chat_room = matrix->get_room_by_id(selected_item->url); + while(window.isOpen()) { bool move_room = chat_page(static_cast(new_tabs[0].page.get()), current_chat_room, tabs, selected_tab, tab_associated_data[selected_tab]); if(!move_room) break; + BodyItem *selected_item = tabs[selected_tab].body->get_selected(); if(!selected_item) break; + current_chat_room = matrix->get_room_by_id(selected_item->url); } + tabs[selected_tab].body->body_item_select_callback = [&submit_handler](BodyItem *body_item) { submit_handler(); }; @@ -1206,15 +1212,19 @@ namespace QuickMedia { } else { page_loop(new_tabs); } + for(Tab &tab : tabs) { tab.page->on_navigate_to_page(tab.body.get()); } + if(content_storage_json.isObject()) { const Json::Value &chapters_json = content_storage_json["chapters"]; if(chapters_json.isObject()) json_chapters = &chapters_json; } + redraw = true; + hide_virtual_keyboard(); }; for(size_t i = 0; i < tabs.size(); ++i) { @@ -2758,8 +2768,8 @@ namespace QuickMedia { } event_idle_handler(event); + comment_input.process_event(event); if(navigation_stage == NavigationStage::REPLYING && !frame_skip_text_entry) { - comment_input.process_event(event); // To prevent pressing enter in comment_input text submit from also immediately sending captcha solution.. is there no better solution? if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Enter) break; @@ -3259,7 +3269,7 @@ namespace QuickMedia { pinned_tab.body->thumbnail_max_size = CHAT_MESSAGE_THUMBNAIL_MAX_SIZE; pinned_tab.body->thumbnail_mask_shader = &circle_mask_shader; pinned_tab.body->attach_side = AttachSide::BOTTOM; - //pinned_tab.body->line_separator_color = sf::Color::Transparent; + pinned_tab.body->line_separator_color = sf::Color::Transparent; pinned_tab.text = sf::Text("Pinned messages", *FontLoader::get_font(FontLoader::FontType::LATIN), tab_text_size); tabs.push_back(std::move(pinned_tab)); @@ -3268,7 +3278,7 @@ namespace QuickMedia { messages_tab.body->thumbnail_max_size = CHAT_MESSAGE_THUMBNAIL_MAX_SIZE; messages_tab.body->thumbnail_mask_shader = &circle_mask_shader; messages_tab.body->attach_side = AttachSide::BOTTOM; - //messages_tab.body->line_separator_color = sf::Color::Transparent; + messages_tab.body->line_separator_color = sf::Color::Transparent; messages_tab.text = sf::Text("Messages", *FontLoader::get_font(FontLoader::FontType::LATIN), tab_text_size); tabs.push_back(std::move(messages_tab)); @@ -3312,6 +3322,9 @@ namespace QuickMedia { const float room_name_total_height = room_name_text_height + room_name_text_padding_y * 2.0f; const float room_avatar_height = 32.0f; + sf::Text room_label(room_tabs[room_selected_tab].page->get_title(), *FontLoader::get_font(FontLoader::FontType::LATIN_BOLD), std::floor(18 * get_ui_scale())); + room_label.setPosition(15.0f, room_name_text_padding_y + 4.0f); + sf::Sprite room_avatar_sprite; auto room_avatar_thumbnail_data = std::make_shared(); @@ -3323,7 +3336,7 @@ namespace QuickMedia { bool setting_read_marker = false; bool redraw = true; - bool draw_room_list = true; + bool draw_room_list = show_room_side_panel; // TODO: Optimize with hash map? auto find_body_item_by_event_id = [](std::shared_ptr *body_items, size_t num_body_items, const std::string &event_id, size_t *index_result = nullptr) -> std::shared_ptr { @@ -4312,9 +4325,12 @@ namespace QuickMedia { base_event_handler(event, PageType::EXIT, tabs[selected_tab].body.get(), nullptr, false, false); event_idle_handler(event); + chat_input.process_event(event); - if(draw_room_list) - room_tabs[room_selected_tab].body->on_event(window, event); + if(draw_room_list) { + if(room_tabs[room_selected_tab].body->on_event(window, event)) + idle_active_handler(); + } if(event.type == sf::Event::KeyPressed && event.key.control && event.key.alt && (chat_state == ChatState::NAVIGATING || chat_state == ChatState::URL_SELECTION)) { if(event.key.code == sf::Keyboard::Up || (event.key.control && event.key.code == sf::Keyboard::K)) { @@ -4584,8 +4600,6 @@ namespace QuickMedia { typing_state_queue.push(false); } } - //chat_input.on_event(event); - chat_input.process_event(event); } } frame_skip_text_entry = false; @@ -4831,14 +4845,6 @@ namespace QuickMedia { window.clear(back_color); - if(draw_room_list) { - sf::RectangleShape room_list_background(this->body_size); - room_list_background.setPosition(this->body_pos); - room_list_background.setFillColor(sf::Color(31, 35, 41)); - window.draw(room_list_background); - room_tabs[room_selected_tab].body->draw(window, this->body_pos, this->body_size, Json::Value::nullSingleton()); - } - const float width_per_tab = body_size.x / tabs.size(); tab_background.setSize(sf::Vector2f(std::floor(width_per_tab - tab_margin_x * 2.0f), tab_height)); @@ -4848,8 +4854,8 @@ namespace QuickMedia { tabs[selected_tab].body->draw(window, body_pos, body_size); const float tab_y = tab_spacer_height + std::floor(tab_vertical_offset + tab_height * 0.5f - (tab_text_size + 5.0f) * 0.5f) + room_name_padding_y; - tab_shade.setSize(sf::Vector2f(window_size.x, tab_shade_height)); - window.draw(tab_shade); + //tab_shade.setSize(sf::Vector2f(window_size.x, tab_shade_height)); + //window.draw(tab_shade); if(selected_tab == MESSAGES_TAB_INDEX || selected_tab == PINNED_TAB_INDEX) { float room_name_text_offset_x = 0.0f; @@ -4865,6 +4871,18 @@ namespace QuickMedia { window.draw(room_name_text); } + if(draw_room_list) { + sf::RectangleShape room_list_background(sf::Vector2f(this->body_size.x, window_size.y)); + //room_list_background.setPosition(this->body_pos); + room_list_background.setFillColor(sf::Color(31, 35, 41)); + glEnable(GL_SCISSOR_TEST); + glScissor(0.0f, 0.0f, this->body_size.x, window_size.y); + window.draw(room_list_background); + window.draw(room_label); + room_tabs[room_selected_tab].body->draw(window, sf::Vector2f(0.0f, tab_y), sf::Vector2f(this->body_size.x, window_size.y - tab_y), Json::Value::nullSingleton()); + glDisable(GL_SCISSOR_TEST); + } + int i = 0; for(ChatTab &tab : tabs) { if(i == selected_tab) { @@ -4957,7 +4975,7 @@ namespace QuickMedia { } if(selected_tab == MESSAGES_TAB_INDEX && current_room) { - window.draw(chat_input_shade); + //window.draw(chat_input_shade); chat_input.draw(window); //chat_input.draw(window, false); window.draw(logo_sprite); } diff --git a/src/SearchBar.cpp b/src/SearchBar.cpp index 26b00a4..df7d951 100644 --- a/src/SearchBar.cpp +++ b/src/SearchBar.cpp @@ -39,6 +39,7 @@ namespace QuickMedia { input_masked(input_masked), typing(false), backspace_pressed(false), + mouse_left_inside(false), vertical_pos(0.0f) { text.setFillColor(text_placeholder_color); @@ -97,10 +98,24 @@ namespace QuickMedia { auto clipboard = sf::Clipboard::getString().toUtf8(); append_text(std::string(clipboard.begin(), clipboard.end())); } + if(event.type == sf::Event::TextEntered && event.text.unicode != 8 && event.text.unicode != 127) // 8 = backspace, 127 = del onTextEntered(event.text.unicode); else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Backspace) onTextEntered(8); + + if(is_touch_enabled() && event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left) { + sf::FloatRect box(background.getPosition(), background.getSize()); + if(box.contains(event.mouseButton.x, event.mouseButton.y)) + mouse_left_inside = true; + else + mouse_left_inside = false; + } else if(is_touch_enabled() && event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Left) { + sf::FloatRect box(background.getPosition(), background.getSize()); + if(mouse_left_inside && box.contains(event.mouseButton.x, event.mouseButton.y)) + show_virtual_keyboard(); + mouse_left_inside = false; + } } void SearchBar::update() { diff --git a/src/Text.cpp b/src/Text.cpp index 32ba360..ee6bd55 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -383,7 +383,7 @@ namespace QuickMedia vertices[vertices_index].append({ vertexBottomRight, sf::Color::White, textureBottomRight }); vertices[vertices_index].append({ vertexTopRight, sf::Color::White, textureTopRight }); - glyphPos.x += emoji_rec.width + characterSpacing; + glyphPos.x += std::floor(emoji_rec.width * get_ui_scale()) + characterSpacing; vertices_linear.push_back({vertices_index, vertexStart, 0, codePoint}); } continue; diff --git a/src/Utils.cpp b/src/Utils.cpp index 2c3bfb7..2a36d27 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -7,6 +7,8 @@ namespace QuickMedia { static float scale = 1.0f; static bool scale_set = false; + static bool qm_enable_touch = false; + static bool qm_enable_touch_set = false; static const int XFT_DPI_DEFAULT = 96; // Returns 96 on error @@ -55,4 +57,32 @@ namespace QuickMedia { scale_set = true; return scale; } + + void show_virtual_keyboard() { + if(!is_touch_enabled()) + return; + + fprintf(stderr, "Show virtual keyboard\n"); + system("busctl call --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 SetVisible b true"); + } + + void hide_virtual_keyboard() { + if(!is_touch_enabled()) + return; + + fprintf(stderr, "Hide virtual keyboard\n"); + system("busctl call --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 SetVisible b false"); + } + + bool is_touch_enabled() { + if(qm_enable_touch_set) + return qm_enable_touch; + + const char *qm_enable_touch_env = getenv("QM_ENABLE_TOUCH"); + if(qm_enable_touch_env && qm_enable_touch_env[0] == '1') + qm_enable_touch = true; + + qm_enable_touch_set = true; + return qm_enable_touch; + } } \ No newline at end of file -- cgit v1.2.3