DesktopStatusWindow.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /*
  2. * Copyright (c) 2021, Peter Elliott <pelliott@serenityos.org>
  3. * Copyright (c) 2022, the SerenityOS developers.
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include "DesktopStatusWindow.h"
  8. #include <LibGUI/ConnectionToWindowManagerServer.h>
  9. #include <LibGUI/Desktop.h>
  10. #include <LibGUI/Painter.h>
  11. #include <LibGUI/Widget.h>
  12. #include <LibGfx/Palette.h>
  13. class DesktopStatusWidget : public GUI::Widget {
  14. C_OBJECT(DesktopStatusWidget);
  15. public:
  16. virtual ~DesktopStatusWidget() override = default;
  17. Gfx::IntRect rect_for_desktop(unsigned row, unsigned column) const
  18. {
  19. auto& desktop = GUI::Desktop::the();
  20. auto workspace_columns = desktop.workspace_columns();
  21. auto workspace_rows = desktop.workspace_rows();
  22. auto desktop_width = (width() - gap() * (workspace_columns - 1)) / workspace_columns;
  23. auto desktop_height = (height() - gap() * (workspace_rows - 1)) / workspace_rows;
  24. return {
  25. column * (desktop_width + gap()), row * (desktop_height + gap()),
  26. desktop_width, desktop_height
  27. };
  28. }
  29. virtual void paint_event(GUI::PaintEvent& event) override
  30. {
  31. GUI::Widget::paint_event(event);
  32. GUI::Painter painter(*this);
  33. painter.add_clip_rect(event.rect());
  34. painter.fill_rect({ 0, 0, width(), height() }, palette().button());
  35. auto& desktop = GUI::Desktop::the();
  36. auto active_color = palette().active_window_border1();
  37. auto inactive_color = palette().inactive_window_border1();
  38. for (unsigned row = 0; row < desktop.workspace_rows(); ++row) {
  39. for (unsigned column = 0; column < desktop.workspace_columns(); ++column) {
  40. painter.fill_rect(rect_for_desktop(row, column),
  41. (row == current_row() && column == current_column()) ? active_color : inactive_color);
  42. }
  43. }
  44. }
  45. virtual void mousedown_event(GUI::MouseEvent& event) override
  46. {
  47. auto base_rect = rect_for_desktop(0, 0);
  48. auto row = event.y() / (base_rect.height() + gap());
  49. auto column = event.x() / (base_rect.width() + gap());
  50. // Handle case where divider is clicked.
  51. if (rect_for_desktop(row, column).contains(event.position()))
  52. GUI::ConnectionToWindowManagerServer::the().async_set_workspace(row, column);
  53. }
  54. virtual void mousewheel_event(GUI::MouseEvent& event) override
  55. {
  56. auto& desktop = GUI::Desktop::the();
  57. auto column = current_column();
  58. auto row = current_row();
  59. auto workspace_columns = desktop.workspace_columns();
  60. auto workspace_rows = desktop.workspace_rows();
  61. auto direction = event.wheel_delta_y() < 0 ? 1 : -1;
  62. if (event.modifiers() & Mod_Shift)
  63. column = abs((int)column + direction) % workspace_columns;
  64. else
  65. row = abs((int)row + direction) % workspace_rows;
  66. GUI::ConnectionToWindowManagerServer::the().async_set_workspace(row, column);
  67. }
  68. unsigned current_row() const { return m_current_row; }
  69. void set_current_row(unsigned row) { m_current_row = row; }
  70. unsigned current_column() const { return m_current_column; }
  71. void set_current_column(unsigned column) { m_current_column = column; }
  72. unsigned gap() const { return m_gap; }
  73. private:
  74. DesktopStatusWidget() = default;
  75. unsigned m_gap { 1 };
  76. unsigned m_current_row { 0 };
  77. unsigned m_current_column { 0 };
  78. };
  79. DesktopStatusWindow::DesktopStatusWindow()
  80. {
  81. GUI::Desktop::the().on_receive_screen_rects([&](GUI::Desktop&) {
  82. auto& desktop = GUI::Desktop::the();
  83. if (desktop.workspace_rows() == 1 && desktop.workspace_columns() == 1)
  84. resize(0, 0);
  85. else
  86. resize(28, 16);
  87. update();
  88. });
  89. set_window_type(GUI::WindowType::Applet);
  90. set_has_alpha_channel(true);
  91. m_widget = &set_main_widget<DesktopStatusWidget>();
  92. }
  93. void DesktopStatusWindow::wm_event(GUI::WMEvent& event)
  94. {
  95. if (event.type() == GUI::Event::WM_WorkspaceChanged) {
  96. auto& changed_event = static_cast<GUI::WMWorkspaceChangedEvent&>(event);
  97. m_widget->set_current_row(changed_event.current_row());
  98. m_widget->set_current_column(changed_event.current_column());
  99. update();
  100. }
  101. }