WSWindowSwitcher.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. #include <WindowServer/WSWindowSwitcher.h>
  2. #include <WindowServer/WSWindowManager.h>
  3. #include <WindowServer/WSMessage.h>
  4. #include <SharedGraphics/Font.h>
  5. WSWindowSwitcher::WSWindowSwitcher()
  6. {
  7. }
  8. WSWindowSwitcher::~WSWindowSwitcher()
  9. {
  10. }
  11. void WSWindowSwitcher::set_visible(bool visible)
  12. {
  13. if (m_visible == visible)
  14. return;
  15. m_visible = visible;
  16. if (m_switcher_window)
  17. m_switcher_window->set_visible(visible);
  18. if (!m_visible)
  19. return;
  20. refresh();
  21. }
  22. WSWindow* WSWindowSwitcher::selected_window()
  23. {
  24. if (m_selected_index < 0 || m_selected_index >= m_windows.size())
  25. return nullptr;
  26. return m_windows[m_selected_index].ptr();
  27. }
  28. void WSWindowSwitcher::on_key_event(const WSKeyEvent& event)
  29. {
  30. if (event.type() == WSMessage::KeyUp) {
  31. if (event.key() == Key_Logo) {
  32. if (auto* window = selected_window()) {
  33. WSWindowManager::the().set_active_window(window);
  34. WSWindowManager::the().move_to_front(*window);
  35. }
  36. WSWindowManager::the().set_highlight_window(nullptr);
  37. hide();
  38. }
  39. return;
  40. }
  41. if (event.key() != Key_Tab) {
  42. WSWindowManager::the().set_highlight_window(nullptr);
  43. hide();
  44. return;
  45. }
  46. ASSERT(!m_windows.is_empty());
  47. m_selected_index = (m_selected_index + 1) % m_windows.size();
  48. ASSERT(m_selected_index < m_windows.size());
  49. auto* highlight_window = m_windows.at(m_selected_index).ptr();
  50. ASSERT(highlight_window);
  51. WSWindowManager::the().set_highlight_window(highlight_window);
  52. draw();
  53. WSWindowManager::the().invalidate(m_rect);
  54. }
  55. void WSWindowSwitcher::draw()
  56. {
  57. Painter painter(*m_switcher_window->backing_store());
  58. painter.fill_rect({ { }, m_rect.size() }, Color::LightGray);
  59. painter.draw_rect({ { }, m_rect.size() }, Color::DarkGray);
  60. for (int index = 0; index < m_windows.size(); ++index) {
  61. auto& window = *m_windows.at(index);
  62. Rect item_rect {
  63. padding(),
  64. padding() + index * item_height(),
  65. m_rect.width() - padding() * 2,
  66. item_height()
  67. };
  68. Color text_color;
  69. Color rect_text_color;
  70. if (index == m_selected_index) {
  71. painter.fill_rect(item_rect, Color::from_rgb(0x84351a));
  72. text_color = Color::White;
  73. rect_text_color = Color::LightGray;
  74. } else {
  75. text_color = Color::Black;
  76. rect_text_color = Color::DarkGray;
  77. }
  78. painter.blit(item_rect.location().translated(0, (item_rect.height() - window.icon().height()) / 2), window.icon(), window.icon().rect());
  79. painter.draw_text(item_rect.translated(window.icon().width() + 4, 0), window.title(), WSWindowManager::the().window_title_font(), TextAlignment::CenterLeft, text_color);
  80. painter.draw_text(item_rect, window.rect().to_string(), TextAlignment::CenterRight, rect_text_color);
  81. }
  82. }
  83. void WSWindowSwitcher::refresh()
  84. {
  85. WSWindow* selected_window = nullptr;
  86. if (m_selected_index > 0 && m_windows[m_selected_index])
  87. selected_window = m_windows[m_selected_index].ptr();
  88. m_windows.clear();
  89. m_selected_index = 0;
  90. int window_count = 0;
  91. int longest_title_width = 0;
  92. WSWindowManager::the().for_each_visible_window_of_type_from_back_to_front(WSWindowType::Normal, [&] (WSWindow& window) {
  93. ++window_count;
  94. longest_title_width = max(longest_title_width, WSWindowManager::the().font().width(window.title()));
  95. if (selected_window == &window)
  96. m_selected_index = m_windows.size();
  97. m_windows.append(window.make_weak_ptr());
  98. return IterationDecision::Continue;
  99. });
  100. if (m_windows.is_empty()) {
  101. hide();
  102. return;
  103. }
  104. int space_for_window_rect = 180;
  105. m_rect.set_width(longest_title_width + space_for_window_rect + padding() * 2);
  106. m_rect.set_height(window_count * item_height() + padding() * 2);
  107. m_rect.center_within(WSWindowManager::the().m_screen_rect);
  108. if (!m_switcher_window)
  109. m_switcher_window = make<WSWindow>(*this, WSWindowType::WindowSwitcher);
  110. m_switcher_window->set_rect(m_rect);
  111. draw();
  112. }
  113. void WSWindowSwitcher::on_message(WSMessage&)
  114. {
  115. }