Sfoglia il codice sorgente

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.
Tim Ledbetter 2 anni fa
parent
commit
55d573afa4
2 ha cambiato i file con 41 aggiunte e 17 eliminazioni
  1. 39 16
      Userland/Games/Chess/ChessWidget.cpp
  2. 2 1
      Userland/Games/Chess/ChessWidget.h

+ 39 - 16
Userland/Games/Chess/ChessWidget.cpp

@@ -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 {
-            m_current_marking.from = mouse_to_square(event);
+        } else if (square.has_value()) {
+            m_current_marking.from = square.release_value();
         }
         }
         return;
         return;
     }
     }
     m_board_markings.clear();
     m_board_markings.clear();
 
 
-    auto square = mouse_to_square(event);
-    auto piece = board().get_piece(square);
+    if (!square.has_value())
+        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) {
-        return { 7 - ((event.y() - widget_offset_y) / square_height), (event.x() - widget_offset_x) / square_width };
-    } else {
-        return { (event.y() - widget_offset_y) / square_height, 7 - ((event.x() - widget_offset_x) / square_width) };
-    }
+    auto rank = y / square_height;
+    auto file = x / square_width;
+    if (rank < 0 || file < 0 || rank > 7 || file > 7)
+        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

+ 2 - 1
Userland/Games/Chess/ChessWidget.h

@@ -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; }