1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 03:27:45 +00:00

Chess: Don't attempt to update the board when clicking out of bounds

Previously, clicking outside the bounds of the board when the window
was resized, could cause a crash.
This commit is contained in:
Tim Ledbetter 2023-04-29 16:04:52 +01:00 committed by Jelle Raaijmakers
parent 852bf35c1e
commit 55d573afa4
2 changed files with 41 additions and 17 deletions

View file

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2020-2022, the SerenityOS developers. * Copyright (c) 2020-2022, the SerenityOS developers.
* Copyright (c) 2023, Tim Ledbetter <timledbetter@gmail.com>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
@ -191,25 +192,28 @@ void ChessWidget::mousedown_event(GUI::MouseEvent& event)
if (!frame_inner_rect().contains(event.position())) if (!frame_inner_rect().contains(event.position()))
return; return;
auto square = mouse_to_square(event);
if (event.button() == GUI::MouseButton::Secondary) { if (event.button() == GUI::MouseButton::Secondary) {
if (m_dragging_piece) { if (m_dragging_piece) {
m_dragging_piece = false; m_dragging_piece = false;
set_override_cursor(Gfx::StandardCursor::None); set_override_cursor(Gfx::StandardCursor::None);
m_available_moves.clear(); m_available_moves.clear();
} else { } else if (square.has_value()) {
m_current_marking.from = mouse_to_square(event); m_current_marking.from = square.release_value();
} }
return; return;
} }
m_board_markings.clear(); m_board_markings.clear();
auto square = mouse_to_square(event); if (!square.has_value())
auto piece = board().get_piece(square); return;
auto piece = board().get_piece(square.value());
if (drag_enabled() && piece.color == board().turn() && !m_playback) { if (drag_enabled() && piece.color == board().turn() && !m_playback) {
m_dragging_piece = true; m_dragging_piece = true;
set_override_cursor(Gfx::StandardCursor::Drag); set_override_cursor(Gfx::StandardCursor::Drag);
m_drag_point = { event.position().x() - widget_offset_x, event.position().y() - widget_offset_y }; m_drag_point = { event.position().x() - widget_offset_x, event.position().y() - widget_offset_y };
m_moving_square = square; m_moving_square = square.value();
m_board.generate_moves([&](Chess::Move move) { m_board.generate_moves([&](Chess::Move move) {
if (move.from == m_moving_square) { if (move.from == m_moving_square) {
@ -227,10 +231,14 @@ void ChessWidget::mouseup_event(GUI::MouseEvent& event)
if (!frame_inner_rect().contains(event.position())) if (!frame_inner_rect().contains(event.position()))
return; return;
auto target_square = mouse_to_square(event);
if (event.button() == GUI::MouseButton::Secondary) { if (event.button() == GUI::MouseButton::Secondary) {
if (!target_square.has_value())
return;
m_current_marking.secondary_color = event.shift(); m_current_marking.secondary_color = event.shift();
m_current_marking.alternate_color = event.ctrl(); m_current_marking.alternate_color = event.ctrl();
m_current_marking.to = mouse_to_square(event); m_current_marking.to = target_square.release_value();
auto match_index = m_board_markings.find_first_index(m_current_marking); auto match_index = m_board_markings.find_first_index(m_current_marking);
if (match_index.has_value()) { if (match_index.has_value()) {
m_board_markings.remove(match_index.value()); m_board_markings.remove(match_index.value());
@ -249,9 +257,12 @@ void ChessWidget::mouseup_event(GUI::MouseEvent& event)
set_override_cursor(Gfx::StandardCursor::Hand); set_override_cursor(Gfx::StandardCursor::Hand);
m_available_moves.clear(); m_available_moves.clear();
auto target_square = mouse_to_square(event); if (!target_square.has_value()) {
update();
return;
}
Chess::Move move = { m_moving_square, target_square }; Chess::Move move = { m_moving_square, target_square.release_value() };
if (board().is_promotion_move(move)) { if (board().is_promotion_move(move)) {
auto promotion_dialog = PromotionDialog::construct(*this); auto promotion_dialog = PromotionDialog::construct(*this);
if (promotion_dialog->exec() == PromotionDialog::ExecResult::OK) if (promotion_dialog->exec() == PromotionDialog::ExecResult::OK)
@ -285,9 +296,12 @@ void ChessWidget::mousemove_event(GUI::MouseEvent& event)
if (!m_dragging_piece) { if (!m_dragging_piece) {
auto square = mouse_to_square(event); auto square = mouse_to_square(event);
if (!square.in_bounds()) if (!square.has_value()) {
set_override_cursor(Gfx::StandardCursor::None);
return; return;
auto piece = board().get_piece(square); }
auto piece = board().get_piece(square.release_value());
if (piece.color == board().turn()) if (piece.color == board().turn())
set_override_cursor(Gfx::StandardCursor::Hand); set_override_cursor(Gfx::StandardCursor::Hand);
else else
@ -357,20 +371,29 @@ void ChessWidget::set_piece_set(StringView set)
m_pieces.set({ Chess::Color::Black, Chess::Type::King }, get_piece(set, "black-king.png"sv)); m_pieces.set({ Chess::Color::Black, Chess::Type::King }, get_piece(set, "black-king.png"sv));
} }
Chess::Square ChessWidget::mouse_to_square(GUI::MouseEvent& event) const Optional<Chess::Square> ChessWidget::mouse_to_square(GUI::MouseEvent& event) const
{ {
int const min_size = min(width(), height()); int const min_size = min(width(), height());
int const widget_offset_x = (window()->width() - min_size) / 2; int const widget_offset_x = (window()->width() - min_size) / 2;
int const widget_offset_y = (window()->height() - min_size) / 2; int const widget_offset_y = (window()->height() - min_size) / 2;
auto x = event.x() - widget_offset_x;
auto y = event.y() - widget_offset_y;
if (x < 0 || y < 0 || x > min_size || y > min_size)
return {};
int square_width = min_size / 8; int square_width = min_size / 8;
int square_height = min_size / 8; int square_height = min_size / 8;
if (side() == Chess::Color::White) { auto rank = y / square_height;
return { 7 - ((event.y() - widget_offset_y) / square_height), (event.x() - widget_offset_x) / square_width }; auto file = x / square_width;
} else { if (rank < 0 || file < 0 || rank > 7 || file > 7)
return { (event.y() - widget_offset_y) / square_height, 7 - ((event.x() - widget_offset_x) / square_width) }; return {};
}
if (side() == Chess::Color::White)
return Chess::Square { 7 - rank, file };
return Chess::Square { rank, 7 - file };
} }
RefPtr<Gfx::Bitmap const> ChessWidget::get_piece_graphic(Chess::Piece const& piece) const RefPtr<Gfx::Bitmap const> ChessWidget::get_piece_graphic(Chess::Piece const& piece) const

View file

@ -1,6 +1,7 @@
/* /*
* Copyright (c) 2020-2022, the SerenityOS developers. * Copyright (c) 2020-2022, the SerenityOS developers.
* Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org> * Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2023, Tim Ledbetter <timledbetter@gmail.com>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
@ -44,7 +45,7 @@ public:
void set_piece_set(StringView set); void set_piece_set(StringView set);
DeprecatedString const& piece_set() const { return m_piece_set; }; DeprecatedString const& piece_set() const { return m_piece_set; };
Chess::Square mouse_to_square(GUI::MouseEvent& event) const; Optional<Chess::Square> mouse_to_square(GUI::MouseEvent& event) const;
bool drag_enabled() const { return m_drag_enabled; } bool drag_enabled() const { return m_drag_enabled; }
void set_drag_enabled(bool e) { m_drag_enabled = e; } void set_drag_enabled(bool e) { m_drag_enabled = e; }