ProcessGUI.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. #include "Process.h"
  2. #include "MemoryManager.h"
  3. #include <LibC/errno_numbers.h>
  4. #include <SharedGraphics/Font.h>
  5. #include <WindowServer/WSScreen.h>
  6. #include <WindowServer/WSMessageLoop.h>
  7. #include <WindowServer/WSWindow.h>
  8. #include <WindowServer/WSWindowManager.h>
  9. #include <WindowServer/WSMenuBar.h>
  10. #include <Kernel/BochsVGADevice.h>
  11. //#define LOG_GUI_SYSCALLS
  12. void Process::initialize_gui_statics()
  13. {
  14. new WSMessageLoop;
  15. }
  16. int Process::make_window_id()
  17. {
  18. int new_id = m_next_window_id++;
  19. while (!new_id || m_windows.contains(new_id)) {
  20. new_id = m_next_window_id++;
  21. if (new_id < 0)
  22. new_id = 1;
  23. }
  24. return new_id;
  25. }
  26. static void wait_for_gui_server()
  27. {
  28. // FIXME: Time out after a while and return an error.
  29. while (!WSMessageLoop::the().running())
  30. sleep(10);
  31. }
  32. int Process::gui$create_window(const GUI_WindowParameters* user_params)
  33. {
  34. wait_for_gui_server();
  35. if (!validate_read_typed(user_params))
  36. return -EFAULT;
  37. auto params = *user_params;
  38. Rect rect = params.rect;
  39. if (rect.is_empty())
  40. return -EINVAL;
  41. ProcessPagingScope scope(WSMessageLoop::the().server_process());
  42. int window_id = make_window_id();
  43. if (!window_id)
  44. return -ENOMEM;
  45. auto window = make<WSWindow>(*this, window_id);
  46. if (!window)
  47. return -ENOMEM;
  48. window->set_title(params.title);
  49. window->set_rect(rect);
  50. m_windows.set(window_id, move(window));
  51. #ifdef LOG_GUI_SYSCALLS
  52. dbgprintf("%s<%u> gui$create_window: %d with rect {%d,%d %dx%d}\n", name().characters(), pid(), window_id, rect.x(), rect.y(), rect.width(), rect.height());
  53. #endif
  54. return window_id;
  55. }
  56. int Process::gui$destroy_window(int window_id)
  57. {
  58. #ifdef LOG_GUI_SYSCALLS
  59. dbgprintf("%s<%u> gui$destroy_window (window_id=%d)\n", name().characters(), pid(), window_id);
  60. #endif
  61. if (window_id < 0)
  62. return -EINVAL;
  63. auto it = m_windows.find(window_id);
  64. if (it == m_windows.end())
  65. return -EBADWINDOW;
  66. auto message = make<WSMessage>(WSMessage::WM_DestroyWindow);
  67. WSMessageLoop::the().post_message((*it).value.leak_ptr(), move(message));
  68. m_windows.remove(window_id);
  69. return 0;
  70. }
  71. int Process::gui$get_window_backing_store(int window_id, GUI_WindowBackingStoreInfo* info)
  72. {
  73. #ifdef LOG_GUI_SYSCALLS
  74. dbgprintf("%s<%u> gui$get_window_backing_store (window_id=%d, info=%p)\n", name().characters(), pid(), window_id, info);
  75. #endif
  76. if (!validate_write_typed(info))
  77. return -EFAULT;
  78. if (window_id < 0)
  79. return -EINVAL;
  80. auto it = m_windows.find(window_id);
  81. if (it == m_windows.end())
  82. return -EBADWINDOW;
  83. auto& window = *(*it).value;
  84. WSWindowLocker locker(window);
  85. auto* backing_store = window.backing();
  86. #ifdef BACKING_STORE_DEBUG
  87. dbgprintf("%s<%u> +++ %p[%d] (%dx%d)\n", name().characters(), pid(), backing_store, backing_store->width(), backing_store->height());
  88. #endif
  89. m_retained_backing_stores.append(backing_store);
  90. info->backing_store_id = backing_store;
  91. info->bpp = sizeof(RGBA32);
  92. info->pitch = backing_store->pitch();
  93. info->size = backing_store->size();
  94. info->pixels = reinterpret_cast<RGBA32*>(backing_store->client_region()->laddr().as_ptr());
  95. return 0;
  96. }
  97. int Process::gui$release_window_backing_store(void* backing_store_id)
  98. {
  99. for (size_t i = 0; i < m_retained_backing_stores.size(); ++i) {
  100. if (m_retained_backing_stores[i].ptr() == backing_store_id) {
  101. #ifdef BACKING_STORE_DEBUG
  102. auto* backing_store = m_retained_backing_stores[i].ptr();
  103. dbgprintf("%s<%u> --- %p (%dx%d)\n", name().characters(), pid(), backing_store, backing_store->width(), backing_store->height());
  104. #endif
  105. m_retained_backing_stores.remove(i);
  106. return 0;
  107. }
  108. }
  109. return -EBADBACKING;
  110. }
  111. int Process::gui$invalidate_window(int window_id, const GUI_Rect* a_rect)
  112. {
  113. if (window_id < 0)
  114. return -EINVAL;
  115. if (a_rect && !validate_read_typed(a_rect))
  116. return -EFAULT;
  117. auto it = m_windows.find(window_id);
  118. if (it == m_windows.end())
  119. return -EBADWINDOW;
  120. #ifdef LOG_GUI_SYSCALLS
  121. if (!a_rect)
  122. dbgprintf("%s<%u> gui$invalidate_window (window_id=%d, rect=(entire))\n", name().characters(), pid(), window_id);
  123. else
  124. dbgprintf("%s<%u> gui$invalidate_window (window_id=%d, rect={%d,%d %dx%d})\n", name().characters(), pid(), window_id, a_rect->location.x, a_rect->location.y, a_rect->size.width, a_rect->size.height);
  125. #endif
  126. auto& window = *(*it).value;
  127. Rect rect;
  128. if (a_rect)
  129. rect = *a_rect;
  130. WSMessageLoop::the().post_message(&window, make<WSClientWantsToPaintMessage>(rect));
  131. WSMessageLoop::the().server_process().request_wakeup();
  132. return 0;
  133. }
  134. int Process::gui$notify_paint_finished(int window_id, const GUI_Rect* a_rect)
  135. {
  136. if (window_id < 0)
  137. return -EINVAL;
  138. if (a_rect && !validate_read_typed(a_rect))
  139. return -EFAULT;
  140. auto it = m_windows.find(window_id);
  141. if (it == m_windows.end())
  142. return -EBADWINDOW;
  143. #ifdef LOG_GUI_SYSCALLS
  144. if (!a_rect)
  145. dbgprintf("%s<%u> gui$notify_paint_finished (window_id=%d, rect=(entire))\n", name().characters(), pid(), window_id);
  146. else
  147. dbgprintf("%s<%u> gui$notify_paint_finished (window_id=%d, rect={%d,%d %dx%d})\n", name().characters(), pid(), window_id, a_rect->location.x, a_rect->location.y, a_rect->size.width, a_rect->size.height);
  148. #endif
  149. auto& window = *(*it).value;
  150. Rect rect;
  151. if (a_rect)
  152. rect = *a_rect;
  153. WSMessageLoop::the().post_message(&window, make<WSClientFinishedPaintMessage>(rect));
  154. WSMessageLoop::the().server_process().request_wakeup();
  155. return 0;
  156. }
  157. int Process::gui$get_window_title(int window_id, char* buffer, size_t size)
  158. {
  159. if (window_id < 0)
  160. return -EINVAL;
  161. if (!validate_write(buffer, size))
  162. return -EFAULT;
  163. auto it = m_windows.find(window_id);
  164. if (it == m_windows.end())
  165. return -EBADWINDOW;
  166. auto& window = *(*it).value;
  167. String title;
  168. {
  169. WSWindowLocker locker(window);
  170. title = window.title();
  171. }
  172. if (title.length() > size)
  173. return -ERANGE;
  174. memcpy(buffer, title.characters(), title.length());
  175. return title.length();
  176. }
  177. int Process::gui$set_window_title(int window_id, const char* title, size_t size)
  178. {
  179. if (window_id < 0)
  180. return -EINVAL;
  181. if (!validate_read(title, size))
  182. return -EFAULT;
  183. auto it = m_windows.find(window_id);
  184. if (it == m_windows.end())
  185. return -EBADWINDOW;
  186. auto& window = *(*it).value;
  187. String new_title(title, size);
  188. WSMessageLoop::the().post_message(&window, make<WSSetWindowTitleMessage>(move(new_title)));
  189. WSMessageLoop::the().server_process().request_wakeup();
  190. return 0;
  191. }
  192. int Process::gui$get_window_rect(int window_id, GUI_Rect* rect)
  193. {
  194. if (window_id < 0)
  195. return -EINVAL;
  196. if (!validate_write_typed(rect))
  197. return -EFAULT;
  198. auto it = m_windows.find(window_id);
  199. if (it == m_windows.end())
  200. return -EBADWINDOW;
  201. auto& window = *(*it).value;
  202. {
  203. WSWindowLocker locker(window);
  204. *rect = window.rect();
  205. }
  206. return 0;
  207. }
  208. int Process::gui$set_window_rect(int window_id, const GUI_Rect* rect)
  209. {
  210. if (window_id < 0)
  211. return -EINVAL;
  212. if (!validate_read_typed(rect))
  213. return -EFAULT;
  214. auto it = m_windows.find(window_id);
  215. if (it == m_windows.end())
  216. return -EBADWINDOW;
  217. auto& window = *(*it).value;
  218. Rect new_rect = *rect;
  219. WSMessageLoop::the().post_message(&window, make<WSSetWindowRectMessage>(new_rect));
  220. WSMessageLoop::the().server_process().request_wakeup();
  221. return 0;
  222. }
  223. int Process::gui$set_global_cursor_tracking_enabled(int window_id, bool enabled)
  224. {
  225. if (window_id < 0)
  226. return -EINVAL;
  227. auto it = m_windows.find(window_id);
  228. if (it == m_windows.end())
  229. return -EBADWINDOW;
  230. auto& window = *(*it).value;
  231. WSWindowLocker locker(window);
  232. window.set_global_cursor_tracking_enabled(enabled);
  233. return 0;
  234. }
  235. void Process::destroy_all_menus()
  236. {
  237. if (!WSMessageLoop::the().running())
  238. return;
  239. WSWindowManager::the().destroy_all_menus(*this);
  240. }
  241. void Process::destroy_all_windows()
  242. {
  243. for (auto& it : m_windows) {
  244. auto message = make<WSMessage>(WSMessage::WM_DestroyWindow);
  245. it.value->notify_process_died(Badge<Process>());
  246. WSMessageLoop::the().post_message(it.value.leak_ptr(), move(message));
  247. }
  248. m_windows.clear();
  249. }
  250. DisplayInfo Process::set_video_resolution(int width, int height)
  251. {
  252. DisplayInfo info;
  253. info.width = width;
  254. info.height = height;
  255. info.bpp = 32;
  256. info.pitch = width * 4;
  257. size_t framebuffer_size = width * height * 4 * 2;
  258. if (!m_display_framebuffer_region) {
  259. auto framebuffer_vmo = VMObject::create_framebuffer_wrapper(BochsVGADevice::the().framebuffer_address(), framebuffer_size);
  260. m_display_framebuffer_region = allocate_region_with_vmo(LinearAddress(0xe0000000), framebuffer_size, move(framebuffer_vmo), 0, "framebuffer", true, true);
  261. }
  262. info.framebuffer = m_display_framebuffer_region->laddr().as_ptr();
  263. BochsVGADevice::the().set_resolution(width, height);
  264. return info;
  265. }