|
| 1 | +/* |
| 2 | + * Copyright 2025 elementary, Inc. (https://elementary.io) |
| 3 | + * SPDX-License-Identifier: GPL-3.0-or-later |
| 4 | + */ |
| 5 | + |
| 6 | +public class Gala.MockRootTarget : Object, GestureTarget, RootTarget { |
| 7 | + public struct ReceivedUpdate { |
| 8 | + public UpdateType type; |
| 9 | + public GestureAction action; |
| 10 | + public double progress; |
| 11 | + } |
| 12 | + |
| 13 | + public Clutter.Actor? actor { get { return null; } } |
| 14 | + |
| 15 | + public Gee.LinkedList<ReceivedUpdate?> received_updates { get; construct; } |
| 16 | + |
| 17 | + construct { |
| 18 | + received_updates = new Gee.LinkedList<ReceivedUpdate?> (); |
| 19 | + } |
| 20 | + |
| 21 | + public override void propagate (UpdateType update_type, GestureAction action, double progress) { |
| 22 | + received_updates.add (ReceivedUpdate () { |
| 23 | + type = update_type, |
| 24 | + action = action, |
| 25 | + progress = progress |
| 26 | + }); |
| 27 | + } |
| 28 | +} |
| 29 | + |
| 30 | +internal class Gala.MockGestureBackend : Object, GestureBackend { |
| 31 | +} |
| 32 | + |
| 33 | +public class Gala.GestureControllerTest : TestCase { |
| 34 | + private Settings gala_settings; |
| 35 | + |
| 36 | + private MockGestureBackend? backend; |
| 37 | + private GestureController? controller; |
| 38 | + private MockRootTarget? root_target; |
| 39 | + |
| 40 | + public GestureControllerTest () { |
| 41 | + Object (name: "GestureController"); |
| 42 | + } |
| 43 | + |
| 44 | + construct { |
| 45 | + new GestureSettings (); // Ensure static variables are initialized |
| 46 | + |
| 47 | + // Make sure we configure swipe up to trigger multitasking view |
| 48 | + gala_settings = new GLib.Settings ("io.elementary.desktop.wm.gestures"); |
| 49 | + gala_settings.delay (); |
| 50 | + gala_settings.set_string ("three-finger-swipe-up", "multitasking-view"); |
| 51 | + |
| 52 | + add_test ("initial update", test_initial_update); |
| 53 | + add_test ("simple propagation", test_simple_propagation); |
| 54 | + } |
| 55 | + |
| 56 | + public override void set_up () { |
| 57 | + backend = new MockGestureBackend (); |
| 58 | + |
| 59 | + controller = new GestureController (MULTITASKING_VIEW, new MockWindowManager ()); |
| 60 | + controller.enable_backend (backend); |
| 61 | + |
| 62 | + root_target = new MockRootTarget (); |
| 63 | + root_target.add_gesture_controller (controller); |
| 64 | + } |
| 65 | + |
| 66 | + public override void tear_down () { |
| 67 | + backend = null; |
| 68 | + controller = null; |
| 69 | + root_target = null; |
| 70 | + } |
| 71 | + |
| 72 | + private void test_initial_update () { |
| 73 | + // Test that we got the initial update when the controller was attached |
| 74 | + assert_cmpint (root_target.received_updates.size, EQ, 1); |
| 75 | + |
| 76 | + var sync_update = root_target.received_updates.poll (); |
| 77 | + |
| 78 | + assert_true (sync_update != null); |
| 79 | + assert_cmpint (sync_update.type, EQ, GestureTarget.UpdateType.UPDATE); |
| 80 | + assert_cmpint (sync_update.action, EQ, GestureAction.MULTITASKING_VIEW); |
| 81 | + assert_cmpfloat (sync_update.progress, EQ, 0.0); |
| 82 | + |
| 83 | + assert_true (root_target.received_updates.is_empty); |
| 84 | + } |
| 85 | + |
| 86 | + private void test_simple_propagation () { |
| 87 | + root_target.received_updates.poll (); // Remove the initial update |
| 88 | + |
| 89 | + // Test a simple propagation flow |
| 90 | + var gesture = new Gesture () { |
| 91 | + type = TOUCHPAD_SWIPE, |
| 92 | + direction = UP, |
| 93 | + fingers = 3, |
| 94 | + }; |
| 95 | + |
| 96 | + var recognizing = backend.on_gesture_detected (gesture, 0); |
| 97 | + |
| 98 | + assert_true (recognizing); |
| 99 | + assert_true (root_target.received_updates.is_empty); |
| 100 | + assert_true (controller.recognizing); |
| 101 | + |
| 102 | + backend.on_begin (0, 0); |
| 103 | + |
| 104 | + assert_true (root_target.received_updates.size == 1); |
| 105 | + |
| 106 | + var update = root_target.received_updates.poll (); |
| 107 | + assert_true (update != null); |
| 108 | + assert_true (update.type == START); |
| 109 | + assert_true (update.action == MULTITASKING_VIEW); |
| 110 | + assert_true (update.progress == 0.0); |
| 111 | + |
| 112 | + backend.on_update (0.25, 0); |
| 113 | + backend.on_update (0.5, 0); |
| 114 | + |
| 115 | + assert_cmpfloat (controller.progress, EQ, 0.5); |
| 116 | + |
| 117 | + backend.on_update (0.75, 0); |
| 118 | + backend.on_update (1.0, 0); |
| 119 | + |
| 120 | + assert_true (root_target.received_updates.size == 4); |
| 121 | + |
| 122 | + for (int i = 0; i < 4; i++) { |
| 123 | + update = root_target.received_updates.poll (); |
| 124 | + assert_true (update != null); |
| 125 | + assert_true (update.type == UPDATE); |
| 126 | + assert_true (update.action == MULTITASKING_VIEW); |
| 127 | + assert_cmpfloat (update.progress, EQ, (i + 1) * 0.25); |
| 128 | + } |
| 129 | + |
| 130 | + backend.on_end (1.0, 0); |
| 131 | + |
| 132 | + assert_true (root_target.received_updates.size == 3); |
| 133 | + |
| 134 | + update = root_target.received_updates.poll (); |
| 135 | + assert_true (update != null); |
| 136 | + assert_true (update.type == UPDATE); |
| 137 | + assert_true (update.action == MULTITASKING_VIEW); |
| 138 | + assert_cmpfloat (update.progress, EQ, 1.0); |
| 139 | + |
| 140 | + update = root_target.received_updates.poll (); |
| 141 | + assert_true (update != null); |
| 142 | + assert_true (update.type == COMMIT); |
| 143 | + assert_true (update.action == MULTITASKING_VIEW); |
| 144 | + assert_cmpfloat (update.progress, EQ, 1.0); |
| 145 | + |
| 146 | + update = root_target.received_updates.poll (); |
| 147 | + assert_true (update != null); |
| 148 | + assert_true (update.type == END); |
| 149 | + assert_true (update.action == MULTITASKING_VIEW); |
| 150 | + assert_cmpfloat (update.progress, EQ, 1.0); |
| 151 | + |
| 152 | + assert_true (root_target.received_updates.is_empty); |
| 153 | + |
| 154 | + assert_false (controller.recognizing); |
| 155 | + assert_cmpfloat (controller.progress, EQ, 1.0); |
| 156 | + |
| 157 | + assert_finalize_object<MockRootTarget> (ref root_target); |
| 158 | + assert_finalize_object<GestureController> (ref controller); |
| 159 | + assert_finalize_object<MockGestureBackend> (ref backend); |
| 160 | + } |
| 161 | +} |
| 162 | + |
| 163 | +public int main (string[] args) { |
| 164 | + return new Gala.GestureControllerTest ().run (args); |
| 165 | +} |
0 commit comments