浏览代码

WindowServer: Introduce the window roll-up feature

The roll-up feature allows the user to set the window content to be
hidden, while retaining the window title bar visibility.
While in roll-up mode, the window height size is not changeable.
However, tiling the window or maximizing (as well as unmaximize) it will
instruct exiting the roll-up mode.
Liav A 1 年之前
父节点
当前提交
b9141d85d8
共有 2 个文件被更改,包括 54 次插入4 次删除
  1. 47 4
      Userland/Services/WindowServer/Window.cpp
  2. 7 0
      Userland/Services/WindowServer/Window.h

+ 47 - 4
Userland/Services/WindowServer/Window.cpp

@@ -151,6 +151,9 @@ void Window::set_rect(Gfx::IntRect const& rect)
         return;
     auto old_rect = m_rect;
     m_rect = rect;
+    if (!m_should_show_window_content) {
+        m_rect.set_height(0);
+    }
     if (rect.is_empty()) {
         m_backing_store = nullptr;
     } else if (is_internal() && (!m_backing_store || old_rect.size() != rect.size())) {
@@ -406,10 +409,14 @@ void Window::set_maximized(bool maximized)
         return;
     m_tile_type = maximized ? WindowTileType::Maximized : WindowTileType::None;
     update_window_menu_items();
-    if (maximized)
+    if (maximized) {
+        exit_roll_up_mode();
         set_rect(WindowManager::the().tiled_window_rect(*this));
-    else
+    } else {
+        exit_roll_up_mode();
         set_rect(m_floating_rect);
+    }
+
     m_frame.did_set_maximized({}, maximized);
     send_resize_event_to_client();
     send_move_event_to_client();
@@ -728,6 +735,12 @@ void Window::ensure_window_menu()
 
         m_window_menu->add_item(make<MenuItem>(*m_window_menu, MenuItem::Type::Separator));
 
+        auto roll_up_item = make<MenuItem>(*m_window_menu, (unsigned)WindowMenuAction::ToggleWindowRollUp, "&Roll Up");
+        m_window_menu_roll_up_item = roll_up_item.ptr();
+        m_window_menu_roll_up_item->set_checked(!m_should_show_window_content);
+        roll_up_item->set_checkable(true);
+        m_window_menu->add_item(move(roll_up_item));
+
         auto menubar_visibility_item = make<MenuItem>(*m_window_menu, (unsigned)WindowMenuAction::ToggleMenubarVisibility, "Menu &Bar");
         m_window_menu_menubar_visibility_item = menubar_visibility_item.ptr();
         menubar_visibility_item->set_checkable(true);
@@ -793,6 +806,23 @@ void Window::handle_window_menu_action(WindowMenuAction action)
         invalidate_last_rendered_screen_rects();
         break;
     }
+    case WindowMenuAction::ToggleWindowRollUp: {
+        auto& item = *m_window_menu->item_by_identifier((unsigned)action);
+        frame().invalidate();
+        item.set_checked(!item.is_checked());
+        m_should_show_window_content = !item.is_checked();
+        if (!m_should_show_window_content) {
+            m_saved_before_roll_up_rect = m_rect;
+            m_rect.set_height(0);
+        } else {
+            m_rect.set_height(m_saved_before_roll_up_rect.height());
+        }
+
+        frame().invalidate();
+        recalculate_rect();
+        invalidate_last_rendered_screen_rects();
+        break;
+    }
     case WindowMenuAction::ToggleAlwaysOnTop: {
         auto& item = *m_window_menu->item_by_identifier((unsigned)action);
         auto new_is_checked = !item.is_checked();
@@ -949,12 +979,25 @@ void Window::set_tiled(WindowTileType tile_type, Optional<Screen const&> tile_on
     tile_type_changed(tile_on_screen);
 }
 
+void Window::exit_roll_up_mode()
+{
+    if (m_should_show_window_content)
+        return;
+    m_rect.set_height(m_saved_before_roll_up_rect.height());
+    m_should_show_window_content = true;
+    if (m_window_menu_roll_up_item)
+        m_window_menu_roll_up_item->set_checked(false);
+}
+
 void Window::tile_type_changed(Optional<Screen const&> tile_on_screen)
 {
-    if (m_tile_type != WindowTileType::None)
+    if (m_tile_type != WindowTileType::None) {
+        exit_roll_up_mode();
         set_rect(WindowManager::the().tiled_window_rect(*this, tile_on_screen, m_tile_type));
-    else
+    } else {
         set_rect(m_floating_rect);
+    }
+
     send_resize_event_to_client();
     send_move_event_to_client();
 }

+ 7 - 0
Userland/Services/WindowServer/Window.h

@@ -61,6 +61,7 @@ enum class WindowMenuAction {
     MinimizeOrUnminimize = 0,
     MaximizeOrRestore,
     ToggleMenubarVisibility,
+    ToggleWindowRollUp,
     Close,
     Move,
     ToggleAlwaysOnTop,
@@ -388,6 +389,8 @@ private:
     void tile_type_changed(Optional<Screen const&> = {});
     ErrorOr<Optional<DeprecatedString>> compute_title_username(ConnectionFromClient* client);
 
+    void exit_roll_up_mode();
+
     ConnectionFromClient* m_client { nullptr };
 
     WeakPtr<Window> m_parent_window;
@@ -398,6 +401,7 @@ private:
     DeprecatedString m_title;
     Optional<DeprecatedString> m_title_username;
     Gfx::IntRect m_rect;
+    Gfx::IntRect m_saved_before_roll_up_rect;
     Gfx::IntRect m_saved_nonfullscreen_rect;
     Gfx::IntRect m_taskbar_rect;
     Vector<Screen*, default_screen_count> m_screens;
@@ -436,6 +440,7 @@ private:
     RefPtr<Gfx::Bitmap> m_backing_store;
     RefPtr<Gfx::Bitmap> m_last_backing_store;
     Gfx::IntSize m_backing_store_visible_size {};
+    Gfx::IntSize m_backup_backing_store_visible_size {};
     i32 m_backing_store_serial { -1 };
     i32 m_last_backing_store_serial { -1 };
     int m_window_id { -1 };
@@ -455,11 +460,13 @@ private:
     MenuItem* m_window_menu_maximize_item { nullptr };
     MenuItem* m_window_menu_move_item { nullptr };
     MenuItem* m_window_menu_close_item { nullptr };
+    MenuItem* m_window_menu_roll_up_item { nullptr };
     MenuItem* m_window_menu_always_on_top_item { nullptr };
     MenuItem* m_window_menu_menubar_visibility_item { nullptr };
     MenuItem* m_window_menu_add_to_quick_launch_item { nullptr };
     Optional<int> m_progress;
     bool m_should_show_menubar { true };
+    bool m_should_show_window_content { true };
     WindowStack* m_window_stack { nullptr };
     RefPtr<Animation> m_animation;