Skip to content

Commit

Permalink
Exposed ApplicationSelector and wrote better tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mattkae committed Jul 21, 2023
1 parent 11f70a7 commit 2ba5d60
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
#ifndef MIR_APPLICATION_SELECTOR_H
#define MIR_APPLICATION_SELECTOR_H

#include <miral/window_manager_tools.h>
#include <miral/application.h>
#include "window_manager_tools.h"
#include "application.h"

namespace miral
{
Expand Down Expand Up @@ -66,6 +66,10 @@ class ApplicationSelector
/// \return true if it is running, otherwise false
auto is_active() -> bool;

/// Retrieve the focused application.
/// \returns The focused application
auto get_focused() -> Application;

private:
WindowManagerTools tools;

Expand Down
2 changes: 1 addition & 1 deletion src/miral/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ add_library(miral-internal STATIC
join_client_threads.h
window_info_defaults.h
window_specification_internal.cpp window_specification_internal.h
application_selector.cpp application_selector.h
application_selector.cpp
)

# Already implied by the linker's symbol version script, but can avoid accidents
Expand Down
20 changes: 18 additions & 2 deletions src/miral/application_selector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "application_selector.h"
#include <miral/application_selector.h>
#include <miral/application_info.h>
#include <miral/application.h>
#include <mir/log.h>
Expand All @@ -28,7 +28,6 @@ ApplicationSelector::ApplicationSelector(const miral::WindowManagerTools& in_too
void ApplicationSelector::advise_new_app(Application const& application)
{
focus_list.push_back(application);
printf("Online: %d\n", pid_of(application));
}

void ApplicationSelector::advise_focus_gained(WindowInfo const& window_info)
Expand Down Expand Up @@ -88,6 +87,18 @@ void ApplicationSelector::advise_delete_app(Application const& application)
return;
}

if (application == selected)
{
auto new_selected_it = it + 1;
if (new_selected_it == focus_list.end())
new_selected_it = focus_list.begin();

if (focus_list.size() > 1)
selected = *new_selected_it;
else
selected = nullptr;
}

focus_list.erase(it);
}

Expand Down Expand Up @@ -163,4 +174,9 @@ void ApplicationSelector::cancel()
auto ApplicationSelector::is_active() -> bool
{
return originally_selected != nullptr;
}

auto ApplicationSelector::get_focused() -> Application
{
return selected;
}
1 change: 0 additions & 1 deletion src/miral/basic_window_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,6 @@ void miral::BasicWindowManager::remove_window(Application const& application, mi
policy->advise_delete_window(info);

info_for(application).remove_window(info.window());
printf("erased\n");
mru_active_windows.erase(info.window());
fullscreen_surfaces.erase(info.window());
for (auto& area : display_areas)
Expand Down
2 changes: 1 addition & 1 deletion src/miral/minimal_window_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include <miral/minimal_window_manager.h>
#include <miral/toolkit_event.h>
#include <miral/application_info.h>
#include "application_selector.h"
#include <miral/application_selector.h>
#include <linux/input.h>
#include <gmpxx.h>

Expand Down
186 changes: 76 additions & 110 deletions tests/miral/application_selector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "application_selector.h"
#include <miral/application_selector.h>
#include "test_window_manager_tools.h"
#include <mir/scene/session.h>

Expand All @@ -30,134 +30,100 @@ struct ApplicationSelectorTest : mt::TestWindowManagerTools
: mt::TestWindowManagerTools(),
application_selector(window_manager_tools)
{}

auto create_window() -> Window
{
mir::shell::SurfaceSpecification creation_parameters;
creation_parameters.type = mir_window_type_normal;
creation_parameters.focus_mode = MirFocusMode::mir_focus_mode_focusable;
creation_parameters.set_size({600, 400});
auto window = create_and_select_window(creation_parameters);

// Simulates a new application opening and gaining focus
application_selector.advise_new_app(window.application());
application_selector.advise_focus_gained(window_manager_tools.info_for(window));
return window;
}

auto create_window_list(int num_windows) -> std::vector<Window>
{
std::vector<Window> window_list;
for (int index = 0; index < num_windows; index++)
{
window_list.push_back(create_window());
}

return window_list;
}
};

/// Testing if we can cycle through 3 windows and then select one
/// with a "forward" selection strategy.
TEST_F(ApplicationSelectorTest, run_forward)
TEST_F(ApplicationSelectorTest, focused_app_is_latest_selected)
{
// Create three windows on our display
mir::shell::SurfaceSpecification creation_parameters;
creation_parameters.name = "window1";
creation_parameters.type = mir_window_type_normal;
creation_parameters.focus_mode = MirFocusMode::mir_focus_mode_focusable;
creation_parameters.set_size({600, 400});
auto window1 = create_and_select_window(creation_parameters);
creation_parameters.name = "window2";
auto window2 = create_and_select_window(creation_parameters);
creation_parameters.name = "window3";
auto window3 = create_and_select_window(creation_parameters);

// Inform the application selector about the windows
application_selector.advise_new_app(window1.application());
application_selector.advise_focus_gained(window_manager_tools.info_for(window1));
application_selector.advise_new_app(window2.application());
application_selector.advise_focus_gained(window_manager_tools.info_for(window2));
application_selector.advise_new_app(window3.application());
application_selector.advise_focus_gained(window_manager_tools.info_for(window3));

// Make sure that window3 (the last one added) is the active one
EXPECT_TRUE(window3 == basic_window_manager.active_window());

// Start the selector and assert that the selected application is window2
auto application = application_selector.next(false);
EXPECT_TRUE(application == window2.application());

// Call next and assert that we have moved to window1
application = application_selector.next(false);
EXPECT_TRUE(application == window1.application());

// Stop the selector and assert that window2 is selected
application = application_selector.next(false);
EXPECT_TRUE(application == window3.application());
auto windows = create_window_list(3);
EXPECT_TRUE(windows[2].application() == application_selector.get_focused());
}

application_selector.advise_delete_app(window1.application());
application_selector.advise_delete_app(window2.application());
application_selector.advise_delete_app(window3.application());
TEST_F(ApplicationSelectorTest, moving_forward_once_selects_previously_selected_application)
{
auto windows = create_window_list(3);
auto application = application_selector.next(false);
EXPECT_TRUE(application == windows[1].application());
}

/// Testing if we can cycle through 3 windows and then select one
/// with a "reverse" selection strategy.
TEST_F(ApplicationSelectorTest, run_backward)
TEST_F(ApplicationSelectorTest, moving_backward_once_selects_least_recently_selected_app)
{
// Create three windows on our display
mir::shell::SurfaceSpecification creation_parameters;
creation_parameters.name = "window1";
creation_parameters.type = mir_window_type_normal;
creation_parameters.focus_mode = MirFocusMode::mir_focus_mode_focusable;
creation_parameters.set_size({600, 400});
auto window1 = create_and_select_window(creation_parameters);
creation_parameters.name = "window2";
auto window2 = create_and_select_window(creation_parameters);
creation_parameters.name = "window3";
auto window3 = create_and_select_window(creation_parameters);

// Inform the application selector about the windows
application_selector.advise_new_app(window1.application());
application_selector.advise_focus_gained(window_manager_tools.info_for(window1));
application_selector.advise_new_app(window2.application());
application_selector.advise_focus_gained(window_manager_tools.info_for(window2));
application_selector.advise_new_app(window3.application());
application_selector.advise_focus_gained(window_manager_tools.info_for(window3));

// Make sure that window3 (the last one added) is the active one
EXPECT_TRUE(window3 == basic_window_manager.active_window());

// Start the selector and assert that the raised application is window2
auto windows = create_window_list(3);
auto application = application_selector.next(true);
EXPECT_TRUE(application == window1.application());

// Call next and assert that we have moved to window1
application = application_selector.next(true);
EXPECT_TRUE(application == window2.application());
EXPECT_TRUE(application == windows[0].application());
}

// Stop the selector and assert that window1 is selected
application = application_selector.complete();
EXPECT_TRUE(application == window2.application());
TEST_F(ApplicationSelectorTest, can_move_forward_through_all_windows_in_the_list_to_arrive_at_original_window)
{
int num_windows = 3;
auto windows = create_window_list(num_windows);
for (int i = 0; i < 3; i++)
application_selector.next(true);
auto application = application_selector.complete();
EXPECT_TRUE(application == windows[2].application());
}

application_selector.advise_delete_app(window1.application());
application_selector.advise_delete_app(window2.application());
application_selector.advise_delete_app(window3.application());
TEST_F(ApplicationSelectorTest, new_selector_is_not_active)
{
auto windows = create_window_list(3);
EXPECT_FALSE(application_selector.is_active());
}

/// Testing if we can start the selector when there are no sessions started.
TEST_F(ApplicationSelectorTest, run_with_no_sessions)
TEST_F(ApplicationSelectorTest, calling_next_with_no_windows_results_in_nullptr)
{
// Start the selector and assert that an application could not be raised
auto application = application_selector.next(false);
EXPECT_TRUE(application == nullptr);
EXPECT_FALSE(application_selector.is_active());
}

/// Testing if we can cycle through a single window successfully
TEST_F(ApplicationSelectorTest, run_in_circle)
TEST_F(ApplicationSelectorTest, focusing_a_new_window_while_application_selector_is_active_focuses_the_new_app)
{
// Create three windows on our display
mir::shell::SurfaceSpecification creation_parameters;
creation_parameters.name = "window1";
creation_parameters.type = mir_window_type_normal;
creation_parameters.focus_mode = MirFocusMode::mir_focus_mode_focusable;
creation_parameters.set_size({600, 400});
auto window1 = create_and_select_window(creation_parameters);

// Inform the application selector about the window
application_selector.advise_new_app(window1.application());
application_selector.advise_focus_gained(window_manager_tools.info_for(window1));

// Make sure that window3 (the last one added) is the active one
EXPECT_TRUE(window1 == basic_window_manager.active_window());

// Start the selector and assert that the raised application is window2
auto application = application_selector.next(true);
EXPECT_TRUE(application == window1.application());

// Call next and assert that we have moved to window1
application = application_selector.next(true);
EXPECT_TRUE(application == window1.application());
auto windows = create_window_list(3);
application_selector.next(true);
auto new_window = create_window();
auto focused = application_selector.get_focused();
EXPECT_TRUE(focused == new_window.application());
}

// Stop the selector and assert that window1 is selected
application = application_selector.complete();
EXPECT_TRUE(application == window1.application());
TEST_F(ApplicationSelectorTest, apps_added_while_selection_is_active_get_added_to_end_of_list)
{
auto windows = create_window_list(3);
application_selector.next(false);
auto new_window = create_window();
auto application = application_selector.next(true);
EXPECT_TRUE(application == windows[0].application());
}

application_selector.advise_delete_app(window1.application());
TEST_F(ApplicationSelectorTest, deleting_selected_app_makes_the_next_app_selected)
{
auto windows = create_window_list(3);
application_selector.next(false); // windows[1] is selected
application_selector.advise_focus_gained(window_manager_tools.info_for(windows[1]));
application_selector.advise_delete_app(windows[1].application());
auto application = application_selector.get_focused();
EXPECT_TRUE(application == windows[0].application());
}

0 comments on commit 2ba5d60

Please sign in to comment.