Skip to content

Commit

Permalink
WindowServer: Add API to change virtual desktop settings
Browse files Browse the repository at this point in the history
This also adds the ability to query how many virtual desktops are
set up, and for the Taskbar to be notified when the active virtual
desktop has changed.
  • Loading branch information
tomuta authored and awesomekling committed Jul 3, 2021
1 parent 584b144 commit 7984c28
Show file tree
Hide file tree
Showing 21 changed files with 383 additions and 64 deletions.
3 changes: 3 additions & 0 deletions Base/etc/WindowServer.ini
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,6 @@ Mode=stretch
[Applet]
Order=CPUGraph,MemoryGraph,Network,ClipboardHistory,Audio

[VirtualDesktops]
Rows=2
Columns=2
5 changes: 4 additions & 1 deletion Userland/Libraries/LibGUI/Desktop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Desktop::Desktop()
{
}

void Desktop::did_receive_screen_rects(Badge<WindowServerConnection>, const Vector<Gfx::IntRect, 4>& rects, size_t main_screen_index)
void Desktop::did_receive_screen_rects(Badge<WindowServerConnection>, const Vector<Gfx::IntRect, 4>& rects, size_t main_screen_index, unsigned virtual_desktop_rows, unsigned virtual_desktop_columns)
{
m_main_screen_index = main_screen_index;
m_rects = rects;
Expand All @@ -36,6 +36,9 @@ void Desktop::did_receive_screen_rects(Badge<WindowServerConnection>, const Vect
} else {
m_bounding_rect = {};
}

m_virtual_desktop_rows = virtual_desktop_rows;
m_virtual_desktop_columns = virtual_desktop_columns;
}

void Desktop::set_background_color(const StringView& background_color)
Expand Down
7 changes: 6 additions & 1 deletion Userland/Libraries/LibGUI/Desktop.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,19 @@ class Desktop {
const Vector<Gfx::IntRect, 4>& rects() const { return m_rects; }
size_t main_screen_index() const { return m_main_screen_index; }

unsigned virtual_desktop_rows() const { return m_virtual_desktop_rows; }
unsigned virtual_desktop_columns() const { return m_virtual_desktop_columns; }

int taskbar_height() const { return TaskbarWindow::taskbar_height(); }

void did_receive_screen_rects(Badge<WindowServerConnection>, const Vector<Gfx::IntRect, 4>&, size_t);
void did_receive_screen_rects(Badge<WindowServerConnection>, const Vector<Gfx::IntRect, 4>&, size_t, unsigned, unsigned);

private:
Vector<Gfx::IntRect, default_screen_rect_count> m_rects;
size_t m_main_screen_index { 0 };
Gfx::IntRect m_bounding_rect;
unsigned m_virtual_desktop_rows { 1 };
unsigned m_virtual_desktop_columns { 1 };
};

}
26 changes: 25 additions & 1 deletion Userland/Libraries/LibGUI/Event.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class Event : public Core::Event {
WM_AppletAreaSizeChanged,
WM_SuperKeyPressed,
WM_SuperSpaceKeyPressed,
WM_VirtualDesktopChanged,
__End_WM_Events,
};

Expand Down Expand Up @@ -135,13 +136,15 @@ class WMWindowRemovedEvent : public WMEvent {

class WMWindowStateChangedEvent : public WMEvent {
public:
WMWindowStateChangedEvent(int client_id, int window_id, int parent_client_id, int parent_window_id, const StringView& title, const Gfx::IntRect& rect, bool is_active, bool is_modal, WindowType window_type, bool is_minimized, bool is_frameless, Optional<int> progress)
WMWindowStateChangedEvent(int client_id, int window_id, int parent_client_id, int parent_window_id, const StringView& title, const Gfx::IntRect& rect, unsigned virtual_desktop_row, unsigned virtual_desktop_column, bool is_active, bool is_modal, WindowType window_type, bool is_minimized, bool is_frameless, Optional<int> progress)
: WMEvent(Event::Type::WM_WindowStateChanged, client_id, window_id)
, m_parent_client_id(parent_client_id)
, m_parent_window_id(parent_window_id)
, m_title(title)
, m_rect(rect)
, m_window_type(window_type)
, m_virtual_desktop_row(virtual_desktop_row)
, m_virtual_desktop_column(virtual_desktop_column)
, m_active(is_active)
, m_modal(is_modal)
, m_minimized(is_minimized)
Expand All @@ -160,13 +163,17 @@ class WMWindowStateChangedEvent : public WMEvent {
bool is_minimized() const { return m_minimized; }
bool is_frameless() const { return m_frameless; }
Optional<int> progress() const { return m_progress; }
unsigned virtual_desktop_row() const { return m_virtual_desktop_row; }
unsigned virtual_desktop_column() const { return m_virtual_desktop_column; }

private:
int m_parent_client_id;
int m_parent_window_id;
String m_title;
Gfx::IntRect m_rect;
WindowType m_window_type;
unsigned m_virtual_desktop_row;
unsigned m_virtual_desktop_column;
bool m_active;
bool m_modal;
bool m_minimized;
Expand Down Expand Up @@ -202,6 +209,23 @@ class WMWindowIconBitmapChangedEvent : public WMEvent {
RefPtr<Gfx::Bitmap> m_bitmap;
};

class WMVirtualDesktopChangedEvent : public WMEvent {
public:
explicit WMVirtualDesktopChangedEvent(int client_id, unsigned current_row, unsigned current_column)
: WMEvent(Event::Type::WM_VirtualDesktopChanged, client_id, 0)
, m_current_row(current_row)
, m_current_column(current_column)
{
}

unsigned current_row() const { return m_current_row; }
unsigned current_column() const { return m_current_column; }

private:
const unsigned m_current_row;
const unsigned m_current_column;
};

class MultiPaintEvent final : public Event {
public:
explicit MultiPaintEvent(const Vector<Gfx::IntRect, 32>& rects, const Gfx::IntSize& window_size)
Expand Down
14 changes: 11 additions & 3 deletions Userland/Libraries/LibGUI/WindowManagerServerConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ WindowManagerServerConnection& WindowManagerServerConnection::the()
}

void WindowManagerServerConnection::window_state_changed(i32 wm_id, i32 client_id, i32 window_id,
i32 parent_client_id, i32 parent_window_id, bool is_active, bool is_minimized, bool is_modal,
bool is_frameless, i32 window_type, String const& title, Gfx::IntRect const& rect, Optional<i32> const& progress)
i32 parent_client_id, i32 parent_window_id, u32 virtual_desktop_row, u32 virtual_desktop_column,
bool is_active, bool is_minimized, bool is_modal, bool is_frameless, i32 window_type,
String const& title, Gfx::IntRect const& rect, Optional<i32> const& progress)
{
if (auto* window = Window::from_window_id(wm_id))
Core::EventLoop::current().post_event(*window, make<WMWindowStateChangedEvent>(client_id, window_id, parent_client_id, parent_window_id, title, rect, is_active, is_modal, static_cast<WindowType>(window_type), is_minimized, is_frameless, progress));
Core::EventLoop::current().post_event(*window, make<WMWindowStateChangedEvent>(client_id, window_id, parent_client_id, parent_window_id, title, rect, virtual_desktop_row, virtual_desktop_column, is_active, is_modal, static_cast<WindowType>(window_type), is_minimized, is_frameless, progress));
}

void WindowManagerServerConnection::applet_area_size_changed(i32 wm_id, const Gfx::IntSize& size)
Expand Down Expand Up @@ -63,4 +64,11 @@ void WindowManagerServerConnection::super_space_key_pressed(i32 wm_id)
if (auto* window = Window::from_window_id(wm_id))
Core::EventLoop::current().post_event(*window, make<WMSuperSpaceKeyPressedEvent>(wm_id));
}

void WindowManagerServerConnection::virtual_desktop_changed(i32 wm_id, u32 row, u32 column)
{
if (auto* window = Window::from_window_id(wm_id))
Core::EventLoop::current().post_event(*window, make<WMVirtualDesktopChangedEvent>(wm_id, row, column));
}

}
3 changes: 2 additions & 1 deletion Userland/Libraries/LibGUI/WindowManagerServerConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@ class WindowManagerServerConnection final

private:
virtual void window_removed(i32, i32, i32) override;
virtual void window_state_changed(i32, i32, i32, i32, i32, bool, bool, bool, bool, i32, String const&, Gfx::IntRect const&, Optional<i32> const&) override;
virtual void window_state_changed(i32, i32, i32, i32, i32, u32, u32, bool, bool, bool, bool, i32, String const&, Gfx::IntRect const&, Optional<i32> const&) override;
virtual void window_icon_bitmap_changed(i32, i32, i32, Gfx::ShareableBitmap const&) override;
virtual void window_rect_changed(i32, i32, i32, Gfx::IntRect const&) override;
virtual void applet_area_size_changed(i32, Gfx::IntSize const&) override;
virtual void super_key_pressed(i32) override;
virtual void super_space_key_pressed(i32) override;
virtual void virtual_desktop_changed(i32, u32, u32) override;
};

}
8 changes: 4 additions & 4 deletions Userland/Libraries/LibGUI/WindowServerConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ WindowServerConnection::WindowServerConnection()
// All we have to do is wait for it to arrive. This avoids a round-trip during application startup.
auto message = wait_for_specific_message<Messages::WindowClient::FastGreet>();
set_system_theme_from_anonymous_buffer(message->theme_buffer());
Desktop::the().did_receive_screen_rects({}, message->screen_rects(), message->main_screen_index());
Desktop::the().did_receive_screen_rects({}, message->screen_rects(), message->main_screen_index(), message->virtual_desktop_rows(), message->virtual_desktop_columns());
Gfx::FontDatabase::set_default_font_query(message->default_font_query());
Gfx::FontDatabase::set_fixed_width_font_query(message->fixed_width_font_query());
}

void WindowServerConnection::fast_greet(Vector<Gfx::IntRect> const&, u32, Core::AnonymousBuffer const&, String const&, String const&)
void WindowServerConnection::fast_greet(Vector<Gfx::IntRect> const&, u32, u32, u32, Core::AnonymousBuffer const&, String const&, String const&)
{
// NOTE: This message is handled in the constructor.
}
Expand Down Expand Up @@ -311,9 +311,9 @@ void WindowServerConnection::menu_item_left(i32 menu_id, u32 identifier)
Core::EventLoop::current().post_event(*app, make<ActionEvent>(GUI::Event::ActionLeave, *action));
}

void WindowServerConnection::screen_rects_changed(Vector<Gfx::IntRect> const& rects, u32 main_screen_index)
void WindowServerConnection::screen_rects_changed(Vector<Gfx::IntRect> const& rects, u32 main_screen_index, u32 virtual_desktop_rows, u32 virtual_desktop_columns)
{
Desktop::the().did_receive_screen_rects({}, rects, main_screen_index);
Desktop::the().did_receive_screen_rects({}, rects, main_screen_index, virtual_desktop_rows, virtual_desktop_columns);
Window::for_each_window({}, [&](auto& window) {
Core::EventLoop::current().post_event(window, make<ScreenRectsChangeEvent>(rects, main_screen_index));
});
Expand Down
4 changes: 2 additions & 2 deletions Userland/Libraries/LibGUI/WindowServerConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class WindowServerConnection final
private:
WindowServerConnection();

virtual void fast_greet(Vector<Gfx::IntRect> const&, u32, Core::AnonymousBuffer const&, String const&, String const&) override;
virtual void fast_greet(Vector<Gfx::IntRect> const&, u32, u32, u32, Core::AnonymousBuffer const&, String const&, String const&) override;
virtual void paint(i32, Gfx::IntSize const&, Vector<Gfx::IntRect> const&) override;
virtual void mouse_move(i32, Gfx::IntPoint const&, u32, u32, u32, i32, bool, Vector<String> const&) override;
virtual void mouse_down(i32, Gfx::IntPoint const&, u32, u32, u32, i32) override;
Expand All @@ -44,7 +44,7 @@ class WindowServerConnection final
virtual void menu_item_entered(i32, u32) override;
virtual void menu_item_left(i32, u32) override;
virtual void menu_visibility_did_change(i32, bool) override;
virtual void screen_rects_changed(Vector<Gfx::IntRect> const&, u32) override;
virtual void screen_rects_changed(Vector<Gfx::IntRect> const&, u32, u32, u32) override;
virtual void set_wallpaper_finished(bool) override;
virtual void drag_dropped(i32, Gfx::IntPoint const&, String const&, HashMap<String, ByteBuffer> const&) override;
virtual void drag_accepted() override;
Expand Down
22 changes: 19 additions & 3 deletions Userland/Services/WindowServer/ClientConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ ClientConnection::ClientConnection(NonnullRefPtr<Core::LocalSocket> client_socke
s_connections = new HashMap<int, NonnullRefPtr<ClientConnection>>;
s_connections->set(client_id, *this);

async_fast_greet(Screen::rects(), Screen::main().index(), Gfx::current_system_theme_buffer(), Gfx::FontDatabase::default_font_query(), Gfx::FontDatabase::fixed_width_font_query());
auto& wm = WindowManager::the();
async_fast_greet(Screen::rects(), Screen::main().index(), wm.window_stack_rows(), wm.window_stack_columns(), Gfx::current_system_theme_buffer(), Gfx::FontDatabase::default_font_query(), Gfx::FontDatabase::fixed_width_font_query());
}

ClientConnection::~ClientConnection()
Expand Down Expand Up @@ -84,9 +85,10 @@ void ClientConnection::die()
});
}

void ClientConnection::notify_about_new_screen_rects(Vector<Gfx::IntRect, 4> const& rects, size_t main_screen_index)
void ClientConnection::notify_about_new_screen_rects()
{
async_screen_rects_changed(rects, main_screen_index);
auto& wm = WindowManager::the();
async_screen_rects_changed(Screen::rects(), Screen::main().index(), wm.window_stack_rows(), wm.window_stack_columns());
}

void ClientConnection::create_menubar(i32 menubar_id)
Expand Down Expand Up @@ -323,6 +325,20 @@ Messages::WindowServer::SaveScreenLayoutResponse ClientConnection::save_screen_l
return { success, move(error_msg) };
}

Messages::WindowServer::ApplyVirtualDesktopSettingsResponse ClientConnection::apply_virtual_desktop_settings(u32 rows, u32 columns, bool save)
{
if (rows == 0 || columns == 0 || rows > WindowManager::max_window_stack_rows || columns > WindowManager::max_window_stack_columns)
return { false };

return { WindowManager::the().apply_virtual_desktop_settings(rows, columns, save) };
}

Messages::WindowServer::GetVirtualDesktopSettingsResponse ClientConnection::get_virtual_desktop_settings()
{
auto& wm = WindowManager::the();
return { (unsigned)wm.window_stack_rows(), (unsigned)wm.window_stack_columns(), WindowManager::max_window_stack_rows, WindowManager::max_window_stack_columns };
}

void ClientConnection::show_screen_numbers(bool show)
{
if (m_show_screen_number == show)
Expand Down
4 changes: 3 additions & 1 deletion Userland/Services/WindowServer/ClientConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class ClientConnection final
static ClientConnection* from_client_id(int client_id);
static void for_each_client(Function<void(ClientConnection&)>);

void notify_about_new_screen_rects(const Vector<Gfx::IntRect, 4>&, size_t);
void notify_about_new_screen_rects();
void post_paint_message(Window&, bool ignore_occlusion = false);

Menu* find_menu_by_id(int menu_id)
Expand Down Expand Up @@ -130,6 +130,8 @@ class ClientConnection final
virtual Messages::WindowServer::SetScreenLayoutResponse set_screen_layout(ScreenLayout const&, bool) override;
virtual Messages::WindowServer::GetScreenLayoutResponse get_screen_layout() override;
virtual Messages::WindowServer::SaveScreenLayoutResponse save_screen_layout() override;
virtual Messages::WindowServer::ApplyVirtualDesktopSettingsResponse apply_virtual_desktop_settings(u32, u32, bool) override;
virtual Messages::WindowServer::GetVirtualDesktopSettingsResponse get_virtual_desktop_settings() override;
virtual void show_screen_numbers(bool) override;
virtual void set_window_cursor(i32, i32) override;
virtual void set_window_custom_cursor(i32, Gfx::ShareableBitmap const&) override;
Expand Down
80 changes: 65 additions & 15 deletions Userland/Services/WindowServer/Compositor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1287,11 +1287,7 @@ void Compositor::update_animations(Screen& screen, Gfx::DisjointRectSet& flush_r

void Compositor::create_window_stack_switch_overlay(WindowStack& target_stack)
{
if (m_stack_switch_overlay_timer) {
// Cancel any timer, we're going to delete the overlay
m_stack_switch_overlay_timer->stop();
m_stack_switch_overlay_timer = nullptr;
}
stop_window_stack_switch_overlay_timer();
Screen::for_each([&](auto& screen) {
auto& screen_data = m_screen_data[screen.index()];
screen_data.m_window_stack_switch_overlay = nullptr; // delete it first
Expand All @@ -1301,20 +1297,45 @@ void Compositor::create_window_stack_switch_overlay(WindowStack& target_stack)
});
}

void Compositor::remove_window_stack_switch_overlays()
{
Screen::for_each([&](auto& screen) {
auto& screen_data = m_screen_data[screen.index()];
screen_data.m_window_stack_switch_overlay = nullptr;
return IterationDecision::Continue;
});
}

void Compositor::stop_window_stack_switch_overlay_timer()
{
if (m_stack_switch_overlay_timer) {
// Cancel any timer, we're going to delete the overlay
m_stack_switch_overlay_timer->stop();
m_stack_switch_overlay_timer = nullptr;
}
}

void Compositor::start_window_stack_switch_overlay_timer()
{
if (m_stack_switch_overlay_timer) {
m_stack_switch_overlay_timer->stop();
m_stack_switch_overlay_timer = nullptr;
}
bool have_overlay = false;
Screen::for_each([&](auto& screen) {
auto& screen_data = m_screen_data[screen.index()];
if (screen_data.m_window_stack_switch_overlay) {
have_overlay = true;
return IterationDecision::Break;
}
return IterationDecision::Continue;
});
if (!have_overlay)
return;
m_stack_switch_overlay_timer = Core::Timer::create_single_shot(
500,
[this] {
Screen::for_each([&](auto& screen) {
auto& screen_data = m_screen_data[screen.index()];
screen_data.m_window_stack_switch_overlay = nullptr;
return IterationDecision::Continue;
});
remove_window_stack_switch_overlays();
},
this);
m_stack_switch_overlay_timer->start();
Expand Down Expand Up @@ -1349,7 +1370,26 @@ void Compositor::finish_window_stack_switch()
start_window_stack_switch_overlay_timer();
}

void Compositor::switch_to_window_stack(WindowStack& new_window_stack)
void Compositor::set_current_window_stack_no_transition(WindowStack& new_window_stack)
{
if (m_transitioning_to_window_stack) {
finish_window_stack_switch();
VERIFY(!m_window_stack_transition_animation);
VERIFY(!m_transitioning_to_window_stack);
}
if (m_current_window_stack == &new_window_stack)
return;
m_current_window_stack = &new_window_stack;
invalidate_for_window_stack_merge_or_change();
}

void Compositor::invalidate_for_window_stack_merge_or_change()
{
invalidate_occlusions();
invalidate_screen();
}

void Compositor::switch_to_window_stack(WindowStack& new_window_stack, bool show_overlay)
{
if (m_transitioning_to_window_stack) {
if (m_transitioning_to_window_stack == &new_window_stack)
Expand All @@ -1363,8 +1403,13 @@ void Compositor::switch_to_window_stack(WindowStack& new_window_stack)

if (&new_window_stack == m_current_window_stack) {
// So that the user knows which stack they're on, show the overlay briefly
create_window_stack_switch_overlay(*m_current_window_stack);
start_window_stack_switch_overlay_timer();
if (show_overlay) {
create_window_stack_switch_overlay(*m_current_window_stack);
start_window_stack_switch_overlay_timer();
} else {
stop_window_stack_switch_overlay_timer();
remove_window_stack_switch_overlays();
}
return;
}
VERIFY(!m_transitioning_to_window_stack);
Expand All @@ -1387,8 +1432,13 @@ void Compositor::switch_to_window_stack(WindowStack& new_window_stack)
m_transitioning_to_window_stack->set_transition_offset({}, { -delta_x, -delta_y });
m_current_window_stack->set_transition_offset({}, {});

create_window_stack_switch_overlay(*m_transitioning_to_window_stack);
// We start the timer when the animation ends!
if (show_overlay) {
// We start the timer when the animation ends!
create_window_stack_switch_overlay(*m_transitioning_to_window_stack);
} else {
stop_window_stack_switch_overlay_timer();
remove_window_stack_switch_overlays();
}

VERIFY(!m_window_stack_transition_animation);
m_window_stack_transition_animation = Animation::create();
Expand Down
Loading

0 comments on commit 7984c28

Please sign in to comment.