GWindow.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. #include "GWindow.h"
  2. #include "GEvent.h"
  3. #include "GEventLoop.h"
  4. #include "GWidget.h"
  5. #include <SharedGraphics/GraphicsBitmap.h>
  6. #include <LibC/gui.h>
  7. #include <LibC/stdio.h>
  8. #include <LibC/stdlib.h>
  9. #include <LibC/unistd.h>
  10. #include <AK/HashMap.h>
  11. static HashMap<int, GWindow*>* s_windows;
  12. static HashMap<int, GWindow*>& windows()
  13. {
  14. if (!s_windows)
  15. s_windows = new HashMap<int, GWindow*>;
  16. return *s_windows;
  17. }
  18. GWindow* GWindow::from_window_id(int window_id)
  19. {
  20. auto it = windows().find(window_id);
  21. if (it != windows().end())
  22. return (*it).value;
  23. return nullptr;
  24. }
  25. GWindow::GWindow(GObject* parent)
  26. : GObject(parent)
  27. {
  28. m_rect_when_windowless = { 100, 400, 140, 140 };
  29. m_title_when_windowless = "GWindow";
  30. }
  31. GWindow::~GWindow()
  32. {
  33. hide();
  34. }
  35. void GWindow::close()
  36. {
  37. delete_later();
  38. }
  39. void GWindow::show()
  40. {
  41. if (m_window_id)
  42. return;
  43. GUI_WindowParameters wparams;
  44. wparams.rect = m_rect_when_windowless;
  45. wparams.background_color = 0xffc0c0;
  46. strcpy(wparams.title, m_title_when_windowless.characters());
  47. m_window_id = gui_create_window(&wparams);
  48. if (m_window_id < 0) {
  49. perror("gui_create_window");
  50. exit(1);
  51. }
  52. windows().set(m_window_id, this);
  53. update();
  54. }
  55. void GWindow::hide()
  56. {
  57. if (!m_window_id)
  58. return;
  59. windows().remove(m_window_id);
  60. int rc = gui_destroy_window(m_window_id);
  61. if (rc < 0) {
  62. perror("gui_destroy_window");
  63. exit(1);
  64. }
  65. }
  66. void GWindow::set_title(String&& title)
  67. {
  68. dbgprintf("GWindow::set_title \"%s\"\n", title.characters());
  69. m_title_when_windowless = title;
  70. if (m_window_id) {
  71. int rc = gui_set_window_title(m_window_id, title.characters(), title.length());
  72. if (rc < 0) {
  73. perror("gui_set_window_title");
  74. exit(1);
  75. }
  76. }
  77. }
  78. String GWindow::title() const
  79. {
  80. if (m_window_id) {
  81. char buffer[256];
  82. int rc = gui_get_window_title(m_window_id, buffer, sizeof(buffer));
  83. ASSERT(rc >= 0);
  84. return String(buffer, rc);
  85. }
  86. return m_title_when_windowless;
  87. }
  88. void GWindow::set_rect(const Rect& a_rect)
  89. {
  90. dbgprintf("GWindow::set_rect! %d,%d %dx%d\n", a_rect.x(), a_rect.y(), a_rect.width(), a_rect.height());
  91. m_rect_when_windowless = a_rect;
  92. if (m_window_id) {
  93. GUI_Rect rect = a_rect;
  94. int rc = gui_set_window_rect(m_window_id, &rect);
  95. ASSERT(rc == 0);
  96. }
  97. }
  98. void GWindow::event(GEvent& event)
  99. {
  100. if (event.is_mouse_event()) {
  101. if (m_global_cursor_tracking_widget) {
  102. // FIXME: This won't work for widgets-within-widgets.
  103. auto& mouse_event = static_cast<GMouseEvent&>(event);
  104. Point local_point { mouse_event.x() - m_global_cursor_tracking_widget->relative_rect().x(), mouse_event.y() - m_global_cursor_tracking_widget->relative_rect().y() };
  105. auto local_event = make<GMouseEvent>(event.type(), local_point, mouse_event.buttons(), mouse_event.button());
  106. m_global_cursor_tracking_widget->event(*local_event);
  107. }
  108. if (!m_main_widget)
  109. return;
  110. auto& mouse_event = static_cast<GMouseEvent&>(event);
  111. if (m_main_widget) {
  112. auto result = m_main_widget->hit_test(mouse_event.x(), mouse_event.y());
  113. auto local_event = make<GMouseEvent>(event.type(), Point { result.localX, result.localY }, mouse_event.buttons(), mouse_event.button());
  114. ASSERT(result.widget);
  115. return result.widget->event(*local_event);
  116. }
  117. return;
  118. }
  119. if (event.is_paint_event()) {
  120. if (!m_main_widget)
  121. return;
  122. auto& paint_event = static_cast<GPaintEvent&>(event);
  123. auto rect = paint_event.rect();
  124. if (rect.is_empty())
  125. rect = m_main_widget->rect();
  126. m_main_widget->event(*make<GPaintEvent>(rect));
  127. if (m_window_id) {
  128. GUI_Rect gui_rect = rect;
  129. int rc = gui_notify_paint_finished(m_window_id, &gui_rect);
  130. ASSERT(rc == 0);
  131. }
  132. return;
  133. }
  134. if (event.is_key_event()) {
  135. if (!m_focused_widget)
  136. return;
  137. return m_focused_widget->event(event);
  138. }
  139. if (event.type() == GEvent::WindowBecameActive || event.type() == GEvent::WindowBecameInactive) {
  140. m_is_active = event.type() == GEvent::WindowBecameActive;
  141. if (m_focused_widget)
  142. m_focused_widget->update();
  143. return;
  144. }
  145. GObject::event(event);
  146. }
  147. bool GWindow::is_visible() const
  148. {
  149. return false;
  150. }
  151. void GWindow::update(const Rect& a_rect)
  152. {
  153. if (!m_window_id)
  154. return;
  155. GUI_Rect rect = a_rect;
  156. int rc = gui_invalidate_window(m_window_id, a_rect.is_null() ? nullptr : &rect);
  157. ASSERT(rc == 0);
  158. }
  159. void GWindow::set_main_widget(GWidget* widget)
  160. {
  161. if (m_main_widget == widget)
  162. return;
  163. m_main_widget = widget;
  164. if (widget)
  165. widget->set_window(this);
  166. update();
  167. }
  168. void GWindow::set_focused_widget(GWidget* widget)
  169. {
  170. if (m_focused_widget == widget)
  171. return;
  172. if (m_focused_widget) {
  173. GEventLoop::main().post_event(m_focused_widget, make<GEvent>(GEvent::FocusOut));
  174. m_focused_widget->update();
  175. }
  176. m_focused_widget = widget;
  177. if (m_focused_widget) {
  178. GEventLoop::main().post_event(m_focused_widget, make<GEvent>(GEvent::FocusIn));
  179. m_focused_widget->update();
  180. }
  181. }
  182. void GWindow::set_global_cursor_tracking_widget(GWidget* widget)
  183. {
  184. ASSERT(m_window_id);
  185. if (widget == m_global_cursor_tracking_widget.ptr())
  186. return;
  187. m_global_cursor_tracking_widget = widget ? widget->makeWeakPtr() : nullptr;
  188. gui_set_global_cursor_tracking_enabled(m_window_id, widget != nullptr);
  189. }