test_tap_dance_layers.cpp (23254B)
- // Copyright 2022 Sergey Vlasov (@sigprof)
- // SPDX-License-Identifier: GPL-2.0-or-later
- #include "keyboard_report_util.hpp"
- #include "keycode.h"
- #include "test_common.hpp"
- #include "action_tapping.h"
- #include "test_keymap_key.hpp"
- #include "tap_dance_defs.h"
- using testing::_;
- using testing::InSequence;
- struct TapDanceKeyParams {
- std::string name; // Tap dance name (part of test name)
- uint16_t keycode; // Tap dance keycode (TD(n))
- uint16_t expect_on_tap; // Keycode for single tap
- uint16_t expect_on_hold; // Keycode for single hold (may be MO(1))
- uint16_t expect_on_double_tap; // Keycode for double tap (may be MO(1))
- uint16_t expect_on_double_hold; // Keycode for double hold (may be MO(1))
- };
- struct OtherKeyLayerParams {
- uint16_t keycode; // Keycode in the keymap
- uint16_t expect_on_press; // Keycode to expect on press
- uint16_t expect_on_release; // Keycode to expect on release (may be KC_NO if none)
- };
- struct OtherKeyParams {
- std::string name; // Other key name (part of test name)
- OtherKeyLayerParams l0; // Keycodes for layer 0
- OtherKeyLayerParams l1; // Keycodes for layer 1
- };
- typedef std::tuple<TapDanceKeyParams, OtherKeyParams> TapDanceLayersParams;
- class TapDanceLayers : public ::testing::WithParamInterface<TapDanceLayersParams>, public TestFixture {
- protected:
- TapDanceKeyParams tap_dance;
- OtherKeyParams other_key;
- std::unique_ptr<KeymapKey> key_td, key_td_l1, key_other, key_other_l1;
- void SetUp() override {
- std::tie(tap_dance, other_key) = GetParam();
- key_td = std::make_unique<KeymapKey>(0, 1, 0, tap_dance.keycode);
- key_td_l1 = std::make_unique<KeymapKey>(1, 1, 0, KC_TRNS);
- key_other = std::make_unique<KeymapKey>(0, 2, 0, other_key.l0.keycode);
- key_other_l1 = std::make_unique<KeymapKey>(1, 2, 0, other_key.l1.keycode);
- set_keymap({*key_td, *key_td_l1, *key_other, *key_other_l1});
- }
- };
- static const TapDanceKeyParams tap_dance_keys[] = {
- TapDanceKeyParams{
- "LayerMove",
- TD(TD_L_MOVE),
- KC_APP,
- KC_APP,
- MO(1),
- MO(1),
- },
- TapDanceKeyParams{
- "LayerToggle",
- TD(TD_L_TOGG),
- KC_APP,
- KC_APP,
- MO(1),
- MO(1),
- },
- TapDanceKeyParams{
- "CustomLT",
- TD(TD_LT_APP),
- KC_APP,
- MO(1),
- KC_RCTL,
- KC_RCTL,
- },
- };
- static const OtherKeyParams other_keys[] = {
- OtherKeyParams{
- "Builtin",
- OtherKeyLayerParams{KC_A, KC_A, KC_NO},
- OtherKeyLayerParams{KC_B, KC_B, KC_NO},
- },
- OtherKeyParams{
- "CustomFast",
- OtherKeyLayerParams{FAST_AB, KC_A, KC_B},
- OtherKeyLayerParams{FAST_CD, KC_C, KC_D},
- },
- OtherKeyParams{
- "CustomSlow",
- OtherKeyLayerParams{SLOW_AB, KC_A, KC_B},
- OtherKeyLayerParams{SLOW_CD, KC_C, KC_D},
- },
- };
- // clang-format off
- INSTANTIATE_TEST_CASE_P(
- Layers,
- TapDanceLayers,
- ::testing::Combine(
- ::testing::ValuesIn(tap_dance_keys),
- ::testing::ValuesIn(other_keys)
- ),
- [](const ::testing::TestParamInfo<TapDanceLayersParams>& info) {
- return std::get<0>(info.param).name + std::get<1>(info.param).name;
- }
- );
- // clang-format on
- // Test single tap of the tap dance key with tapping term delay after the tap.
- TEST_P(TapDanceLayers, SingleTap) {
- TestDriver driver;
- InSequence s;
- // The tap of the tap dance key does not result in sending a report
- // immediately.
- EXPECT_NO_REPORT(driver);
- tap_key(*key_td);
- // After the tapping term expires, a tap event for the single tap keycode
- // is generated.
- idle_for(TAPPING_TERM - 1);
- EXPECT_REPORT(driver, (tap_dance.expect_on_tap));
- EXPECT_EMPTY_REPORT(driver);
- run_one_scan_loop();
- // Pressing the other key produces the reports for the layer 0 mapping of
- // that key.
- EXPECT_REPORT(driver, (other_key.l0.expect_on_press));
- if (other_key.l0.expect_on_release != KC_NO) {
- EXPECT_EMPTY_REPORT(driver);
- }
- key_other->press();
- run_one_scan_loop();
- // Releasing the other key produces the reports for the layer 0 mapping of
- // that key.
- if (other_key.l0.expect_on_release != KC_NO) {
- EXPECT_REPORT(driver, (other_key.l0.expect_on_release));
- }
- EXPECT_EMPTY_REPORT(driver);
- key_other->release();
- run_one_scan_loop();
- }
- // Test single tap of the tap dance key without a delay between the tap dance
- // key and the other key.
- TEST_P(TapDanceLayers, SingleTapFast) {
- TestDriver driver;
- InSequence s;
- // The tap of the tap dance key does not result in sending a report
- // immediately.
- EXPECT_NO_REPORT(driver);
- tap_key(*key_td);
- // A quick press of the other key causes the tap event for the tap dance to
- // be sent before the press event for the other key, and the layer 0
- // mapping is used for the other key.
- EXPECT_REPORT(driver, (tap_dance.expect_on_tap));
- EXPECT_EMPTY_REPORT(driver);
- EXPECT_REPORT(driver, (other_key.l0.expect_on_press));
- if (other_key.l0.expect_on_release != KC_NO) {
- EXPECT_EMPTY_REPORT(driver);
- }
- key_other->press();
- run_one_scan_loop();
- // Releasing the other key produces the reports for the layer 0 mapping of
- // that key.
- if (other_key.l0.expect_on_release != KC_NO) {
- EXPECT_REPORT(driver, (other_key.l0.expect_on_release));
- }
- EXPECT_EMPTY_REPORT(driver);
- key_other->release();
- run_one_scan_loop();
- }
- // Test single hold of the tap dance key with tapping term delay after the hold
- // (test variant for tap dances which switch the layer on hold).
- TEST_P(TapDanceLayers, SingleHoldLayer) {
- if (tap_dance.expect_on_hold != MO(1)) {
- // Do nothing - the SingleHoldKeycode test would run instead.
- return;
- }
- TestDriver driver;
- InSequence s;
- // No report gets sent immediately after the hold of the tap dance key.
- EXPECT_NO_REPORT(driver);
- key_td->press();
- run_one_scan_loop();
- // After the tapping term expires, the tap dance finishes and switches the
- // layer, but does not send a report.
- EXPECT_NO_REPORT(driver);
- idle_for(TAPPING_TERM);
- run_one_scan_loop();
- // Pressing the other key produces the reports for the layer 1 mapping of
- // that key.
- EXPECT_REPORT(driver, (other_key.l1.expect_on_press));
- if (other_key.l1.expect_on_release != KC_NO) {
- EXPECT_EMPTY_REPORT(driver);
- }
- key_other->press();
- run_one_scan_loop();
- // Releasing the tap dance key does not produce a report.
- EXPECT_NO_REPORT(driver);
- key_td->release();
- run_one_scan_loop();
- // Releasing the other key produces the report for the layer 1 mapping of
- // that key.
- if (other_key.l1.expect_on_release != KC_NO) {
- EXPECT_REPORT(driver, (other_key.l1.expect_on_release));
- }
- EXPECT_EMPTY_REPORT(driver);
- key_other->release();
- run_one_scan_loop();
- }
- // Test single hold of the tap dance key with tapping term delay after the hold
- // (test variant for tap dances which send a keycode on single hold).
- TEST_P(TapDanceLayers, SingleHoldKeycode) {
- if (tap_dance.expect_on_hold == MO(1)) {
- // Do nothing - the SingleHoldLayer test would run instead.
- return;
- }
- TestDriver driver;
- InSequence s;
- // No report gets sent immediately after the hold of the tap dance key.
- EXPECT_NO_REPORT(driver);
- key_td->press();
- run_one_scan_loop();
- // After the tapping term expires, the tap dance sends the report with the
- // hold keycode.
- EXPECT_NO_REPORT(driver);
- idle_for(TAPPING_TERM);
- EXPECT_REPORT(driver, (tap_dance.expect_on_hold));
- run_one_scan_loop();
- // Pressing the other key produces the reports for the layer 0 mapping of
- // that key.
- EXPECT_REPORT(driver, (tap_dance.expect_on_hold, other_key.l0.expect_on_press));
- if (other_key.l0.expect_on_release != KC_NO) {
- EXPECT_REPORT(driver, (tap_dance.expect_on_hold));
- }
- key_other->press();
- run_one_scan_loop();
- // Releasing the tap dance key sends the release report for the
- // corresponding hold keycode.
- if (other_key.l0.expect_on_release != KC_NO) {
- EXPECT_EMPTY_REPORT(driver);
- } else {
- EXPECT_REPORT(driver, (other_key.l0.expect_on_press));
- }
- key_td->release();
- run_one_scan_loop();
- // Releasing the other key produces the reports for the layer 0 mapping of
- // that key.
- if (other_key.l0.expect_on_release != KC_NO) {
- EXPECT_REPORT(driver, (other_key.l0.expect_on_release));
- }
- EXPECT_EMPTY_REPORT(driver);
- key_other->release();
- run_one_scan_loop();
- }
- // Test single hold of the tap dance key without tapping term delay after the
- // hold (test variant for tap dances which switch the layer on hold).
- TEST_P(TapDanceLayers, SingleHoldFastLayer) {
- if (tap_dance.expect_on_hold != MO(1)) {
- // Do nothing - the SingleHoldFastKeycode test would run instead.
- return;
- }
- TestDriver driver;
- InSequence s;
- // No report gets sent immediately after the hold of the tap dance key.
- EXPECT_NO_REPORT(driver);
- key_td->press();
- run_one_scan_loop();
- // Pressing the other key produces the reports for the layer 1 mapping of
- // that key.
- EXPECT_REPORT(driver, (other_key.l1.expect_on_press));
- if (other_key.l1.expect_on_release != KC_NO) {
- EXPECT_EMPTY_REPORT(driver);
- }
- key_other->press();
- run_one_scan_loop();
- // Releasing the tap dance key does not produce a report.
- EXPECT_NO_REPORT(driver);
- key_td->release();
- run_one_scan_loop();
- // Releasing the other key produces the reports for the layer 1 mapping of
- // that key.
- if (other_key.l1.expect_on_release != KC_NO) {
- EXPECT_REPORT(driver, (other_key.l1.expect_on_release));
- }
- EXPECT_EMPTY_REPORT(driver);
- key_other->release();
- run_one_scan_loop();
- }
- // Test single hold of the tap dance key without tapping term delay after the hold
- // (test variant for tap dances which send a keycode on single hold).
- TEST_P(TapDanceLayers, SingleHoldFastKeycode) {
- if (tap_dance.expect_on_hold == MO(1)) {
- // Do nothing - the SingleHoldFastLayer test would run instead.
- return;
- }
- TestDriver driver;
- InSequence s;
- // No report gets sent immediately after the hold of the tap dance key.
- EXPECT_NO_REPORT(driver);
- key_td->press();
- run_one_scan_loop();
- // Pressing the other key produces first the report for the tap dance hold
- // keycode, and then the reports for the layer 0 mapping of the other key.
- EXPECT_REPORT(driver, (tap_dance.expect_on_hold));
- EXPECT_REPORT(driver, (tap_dance.expect_on_hold, other_key.l0.expect_on_press));
- if (other_key.l0.expect_on_release != KC_NO) {
- EXPECT_REPORT(driver, (tap_dance.expect_on_hold));
- }
- key_other->press();
- run_one_scan_loop();
- // Releasing the tap dance key sends a release report for the corresponding
- // hold keycode.
- if (other_key.l0.expect_on_release != KC_NO) {
- EXPECT_EMPTY_REPORT(driver);
- } else {
- EXPECT_REPORT(driver, (other_key.l0.expect_on_press));
- }
- key_td->release();
- run_one_scan_loop();
- // Releasing the other key produces the report for the layer 0 mapping of
- // that key.
- if (other_key.l0.expect_on_release != KC_NO) {
- EXPECT_REPORT(driver, (other_key.l0.expect_on_release));
- }
- EXPECT_EMPTY_REPORT(driver);
- key_other->release();
- run_one_scan_loop();
- }
- // Test double tap of the tap dance key with tapping term delay after the hold
- // (test variant for tap dances which switch the layer on double tap).
- TEST_P(TapDanceLayers, DoubleTapLayer) {
- if (tap_dance.expect_on_double_tap != MO(1)) {
- // Do nothing - the DoubleTapKeycode test would run instead.
- return;
- }
- TestDriver driver;
- InSequence s;
- // No report gets sent immediately after the double tap of the tap dance
- // key.
- EXPECT_NO_REPORT(driver);
- tap_key(*key_td);
- tap_key(*key_td);
- // After the tapping term this tap dance does not send a report too.
- EXPECT_NO_REPORT(driver);
- idle_for(TAPPING_TERM);
- run_one_scan_loop();
- // Pressing the other key produces the reports for the layer 1 mapping of
- // that key.
- EXPECT_REPORT(driver, (other_key.l1.expect_on_press));
- if (other_key.l1.expect_on_release != KC_NO) {
- EXPECT_EMPTY_REPORT(driver);
- }
- key_other->press();
- run_one_scan_loop();
- // Releasing the other key produces the report for the layer 1 mapping of
- // that key.
- if (other_key.l1.expect_on_release != KC_NO) {
- EXPECT_REPORT(driver, (other_key.l1.expect_on_release));
- }
- EXPECT_EMPTY_REPORT(driver);
- key_other->release();
- run_one_scan_loop();
- }
- // Test double tap of the tap dance key with tapping term delay after the hold
- // (test variant for tap dances which send a keycode on double tap).
- TEST_P(TapDanceLayers, DoubleTapKeycode) {
- if (tap_dance.expect_on_double_tap == MO(1)) {
- // Do nothing - the DoubleTapLayer test would run instead.
- return;
- }
- TestDriver driver;
- InSequence s;
- // No report gets sent immediately after the double tap of the tap dance
- // key.
- EXPECT_NO_REPORT(driver);
- tap_key(*key_td);
- tap_key(*key_td);
- // After the tapping term this tap dance sends the double tap keycode.
- idle_for(TAPPING_TERM - 1);
- EXPECT_REPORT(driver, (tap_dance.expect_on_double_tap));
- EXPECT_EMPTY_REPORT(driver);
- run_one_scan_loop();
- // Pressing the other key produces the reports for the layer 0 mapping of
- // that key.
- EXPECT_REPORT(driver, (other_key.l0.expect_on_press));
- if (other_key.l0.expect_on_release != KC_NO) {
- EXPECT_EMPTY_REPORT(driver);
- }
- key_other->press();
- run_one_scan_loop();
- // Releasing the other key produces the report for the layer 0 mapping of
- // that key.
- if (other_key.l0.expect_on_release != KC_NO) {
- EXPECT_REPORT(driver, (other_key.l0.expect_on_release));
- }
- EXPECT_EMPTY_REPORT(driver);
- key_other->release();
- run_one_scan_loop();
- }
- // Test double tap of the tap dance key without tapping term delay after the
- // hold (test variant for tap dances which switch the layer on double tap).
- TEST_P(TapDanceLayers, DoubleTapFastLayer) {
- if (tap_dance.expect_on_double_tap != MO(1)) {
- // Do nothing - the DoubleTapFastKeycode test would run instead.
- return;
- }
- TestDriver driver;
- InSequence s;
- // No report gets sent immediately after the double tap of the tap dance
- // key.
- EXPECT_NO_REPORT(driver);
- tap_key(*key_td);
- tap_key(*key_td);
- // Pressing the other key produces the reports for the layer 1 mapping of
- // that key.
- EXPECT_REPORT(driver, (other_key.l1.expect_on_press));
- if (other_key.l1.expect_on_release != KC_NO) {
- EXPECT_EMPTY_REPORT(driver);
- }
- key_other->press();
- run_one_scan_loop();
- // Releasing the other key produces the report for the layer 1 mapping of
- // that key.
- if (other_key.l1.expect_on_release != KC_NO) {
- EXPECT_REPORT(driver, (other_key.l1.expect_on_release));
- }
- EXPECT_EMPTY_REPORT(driver);
- key_other->release();
- run_one_scan_loop();
- }
- // Test double tap of the tap dance key without tapping term delay after the
- // hold (test variant for tap dances which send a keycode on double tap).
- TEST_P(TapDanceLayers, DoubleTapFastKeycode) {
- if (tap_dance.expect_on_double_tap == MO(1)) {
- // Do nothing - the DoubleTapFastLayer test would run instead.
- return;
- }
- TestDriver driver;
- InSequence s;
- // No report gets sent immediately after the double tap of the tap dance
- // key.
- EXPECT_NO_REPORT(driver);
- tap_key(*key_td);
- tap_key(*key_td);
- // Pressing the other key produces first the report for the tap dance
- // double tap keycode, and then the reports for the layer 0 mapping of the
- // other key.
- EXPECT_REPORT(driver, (tap_dance.expect_on_double_tap));
- EXPECT_EMPTY_REPORT(driver);
- EXPECT_REPORT(driver, (other_key.l0.expect_on_press));
- if (other_key.l0.expect_on_release != KC_NO) {
- EXPECT_EMPTY_REPORT(driver);
- }
- key_other->press();
- run_one_scan_loop();
- // Releasing the other key produces the report for the layer 0 mapping of
- // that key.
- if (other_key.l0.expect_on_release != KC_NO) {
- EXPECT_REPORT(driver, (other_key.l0.expect_on_release));
- }
- EXPECT_EMPTY_REPORT(driver);
- key_other->release();
- run_one_scan_loop();
- }
- // Test double hold of the tap dance key with tapping term delay after the hold
- // (test variant for tap dances which switch the layer on double hold).
- TEST_P(TapDanceLayers, DoubleHoldLayer) {
- if (tap_dance.expect_on_double_hold != MO(1)) {
- // Do nothing - the DoubleHoldKeycode test would run instead.
- return;
- }
- TestDriver driver;
- InSequence s;
- // No report gets sent immediately after the double hold of the tap dance
- // key.
- EXPECT_NO_REPORT(driver);
- tap_key(*key_td);
- key_td->press();
- run_one_scan_loop();
- // After the tapping term expires, the tap dance finishes and switches the
- // layer, but does not send a report.
- EXPECT_NO_REPORT(driver);
- idle_for(TAPPING_TERM);
- run_one_scan_loop();
- // Pressing the other key produces the reports for the layer 1 mapping of
- // that key.
- EXPECT_REPORT(driver, (other_key.l1.expect_on_press));
- if (other_key.l1.expect_on_release != KC_NO) {
- EXPECT_EMPTY_REPORT(driver);
- }
- key_other->press();
- run_one_scan_loop();
- // Releasing the tap dance key does not produce a report.
- EXPECT_NO_REPORT(driver);
- key_td->release();
- run_one_scan_loop();
- // Releasing the other key produces the report for the layer 1 mapping of
- // that key.
- if (other_key.l1.expect_on_release != KC_NO) {
- EXPECT_REPORT(driver, (other_key.l1.expect_on_release));
- }
- EXPECT_EMPTY_REPORT(driver);
- key_other->release();
- run_one_scan_loop();
- }
- // Test double hold of the tap dance key with tapping term delay after the hold
- // (test variant for tap dances which send a keycode on double hold).
- TEST_P(TapDanceLayers, DoubleHoldKeycode) {
- if (tap_dance.expect_on_double_hold == MO(1)) {
- // Do nothing - the DoubleHoldLayer test would run instead.
- return;
- }
- TestDriver driver;
- InSequence s;
- // No report gets sent immediately after the double hold of the tap dance
- // key.
- EXPECT_NO_REPORT(driver);
- tap_key(*key_td);
- key_td->press();
- run_one_scan_loop();
- // After the tapping term expires, the tap dance sends the report with the
- // double hold keycode.
- EXPECT_NO_REPORT(driver);
- idle_for(TAPPING_TERM);
- EXPECT_REPORT(driver, (tap_dance.expect_on_double_hold));
- run_one_scan_loop();
- // Pressing the other key produces the reports for the layer 0 mapping of
- // that key.
- EXPECT_REPORT(driver, (tap_dance.expect_on_double_hold, other_key.l0.expect_on_press));
- if (other_key.l0.expect_on_release != KC_NO) {
- EXPECT_REPORT(driver, (tap_dance.expect_on_double_hold));
- }
- key_other->press();
- run_one_scan_loop();
- // Releasing the tap dance key sends the release report for the
- // corresponding double hold keycode.
- if (other_key.l0.expect_on_release != KC_NO) {
- EXPECT_EMPTY_REPORT(driver);
- } else {
- EXPECT_REPORT(driver, (other_key.l0.expect_on_press));
- }
- key_td->release();
- run_one_scan_loop();
- // Releasing the other key produces the reports for the layer 0 mapping of
- // that key.
- if (other_key.l0.expect_on_release != KC_NO) {
- EXPECT_REPORT(driver, (other_key.l0.expect_on_release));
- }
- EXPECT_EMPTY_REPORT(driver);
- key_other->release();
- run_one_scan_loop();
- }
- // Test double hold of the tap dance key without tapping term delay after the
- // hold (test variant for tap dances which switch the layer on double hold).
- TEST_P(TapDanceLayers, DoubleHoldFastLayer) {
- if (tap_dance.expect_on_double_hold != MO(1)) {
- // Do nothing - the DoubleHoldFastKeycode test would run instead.
- return;
- }
- TestDriver driver;
- InSequence s;
- // No report gets sent immediately after the double hold of the tap dance
- // key.
- EXPECT_NO_REPORT(driver);
- tap_key(*key_td);
- key_td->press();
- run_one_scan_loop();
- // Pressing the other key produces the reports for the layer 1 mapping of
- // that key.
- EXPECT_REPORT(driver, (other_key.l1.expect_on_press));
- if (other_key.l1.expect_on_release != KC_NO) {
- EXPECT_EMPTY_REPORT(driver);
- }
- key_other->press();
- run_one_scan_loop();
- // Releasing the tap dance key does not produce a report.
- EXPECT_NO_REPORT(driver);
- key_td->release();
- run_one_scan_loop();
- // Releasing the other key produces the reports for the layer 1 mapping of
- // that key.
- if (other_key.l1.expect_on_release != KC_NO) {
- EXPECT_REPORT(driver, (other_key.l1.expect_on_release));
- }
- EXPECT_EMPTY_REPORT(driver);
- key_other->release();
- run_one_scan_loop();
- }
- // Test double hold of the tap dance key without tapping term delay after the hold
- // (test variant for tap dances which send a keycode on double hold).
- TEST_P(TapDanceLayers, DoubleHoldFastKeycode) {
- if (tap_dance.expect_on_double_hold == MO(1)) {
- // Do nothing - the DoubleHoldFastLayer test would run instead.
- return;
- }
- TestDriver driver;
- InSequence s;
- // No report gets sent immediately after the double hold of the tap dance
- // key.
- EXPECT_NO_REPORT(driver);
- tap_key(*key_td);
- key_td->press();
- run_one_scan_loop();
- // Pressing the other key produces first the report for the tap dance
- // double hold keycode, and then the reports for the layer 0 mapping of the
- // other key.
- EXPECT_REPORT(driver, (tap_dance.expect_on_double_hold));
- EXPECT_REPORT(driver, (tap_dance.expect_on_double_hold, other_key.l0.expect_on_press));
- if (other_key.l0.expect_on_release != KC_NO) {
- EXPECT_REPORT(driver, (tap_dance.expect_on_double_hold));
- }
- key_other->press();
- run_one_scan_loop();
- // Releasing the tap dance key sends a release report for the corresponding
- // double hold keycode.
- if (other_key.l0.expect_on_release != KC_NO) {
- EXPECT_EMPTY_REPORT(driver);
- } else {
- EXPECT_REPORT(driver, (other_key.l0.expect_on_press));
- }
- key_td->release();
- run_one_scan_loop();
- // Releasing the other key produces the report for the layer 0 mapping of
- // that key.
- if (other_key.l0.expect_on_release != KC_NO) {
- EXPECT_REPORT(driver, (other_key.l0.expect_on_release));
- }
- EXPECT_EMPTY_REPORT(driver);
- key_other->release();
- run_one_scan_loop();
- }