diff --git a/Kernel/MemoryManager.cpp b/Kernel/MemoryManager.cpp index 5443b1acc5..18734d32ec 100644 --- a/Kernel/MemoryManager.cpp +++ b/Kernel/MemoryManager.cpp @@ -389,8 +389,11 @@ PageFaultResponse MemoryManager::handle_page_fault(const PageFault& fault) RetainPtr MemoryManager::allocate_physical_page(ShouldZeroFill should_zero_fill) { InterruptDisabler disabler; - if (1 > m_free_physical_pages.size()) + if (1 > m_free_physical_pages.size()) { + kprintf("FUCK! No physical pages available.\n"); + ASSERT_NOT_REACHED(); return { }; + } #ifdef MM_DEBUG dbgprintf("MM: allocate_physical_page vending P%x (%u remaining)\n", m_free_physical_pages.last()->paddr().get(), m_free_physical_pages.size()); #endif @@ -406,8 +409,11 @@ RetainPtr MemoryManager::allocate_physical_page(ShouldZeroFill sho RetainPtr MemoryManager::allocate_supervisor_physical_page() { InterruptDisabler disabler; - if (1 > m_free_supervisor_physical_pages.size()) + if (1 > m_free_supervisor_physical_pages.size()) { + kprintf("FUCK! No physical pages available.\n"); + ASSERT_NOT_REACHED(); return { }; + } #ifdef MM_DEBUG dbgprintf("MM: allocate_supervisor_physical_page vending P%x (%u remaining)\n", m_free_supervisor_physical_pages.last()->paddr().get(), m_free_supervisor_physical_pages.size()); #endif diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index e2606dec28..9090cba844 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -2444,9 +2444,11 @@ void SharedBuffer::destroy_if_unused() if (!m_pid1_retain_count && !m_pid2_retain_count) { LOCKER(shared_buffers().lock()); #ifdef SHARED_BUFFER_DEBUG - dbgprintf("Destroying unused SharedBuffer{%p} (pid1: %d, pid2: %d)\n", this, m_pid1, m_pid2); + dbgprintf("Destroying unused SharedBuffer{%p} id: %d (pid1: %d, pid2: %d)\n", this, m_shared_buffer_id, m_pid1, m_pid2); #endif + size_t count_before = shared_buffers().resource().size(); shared_buffers().resource().remove(m_shared_buffer_id); + ASSERT(count_before != shared_buffers().resource().size()); } } @@ -2473,6 +2475,7 @@ int Process::sys$create_shared_buffer(pid_t peer_pid, size_t size, void** buffer LOCKER(shared_buffers().lock()); int shared_buffer_id = ++s_next_shared_buffer_id; auto shared_buffer = make(m_pid, peer_pid, size); + shared_buffer->m_shared_buffer_id = shared_buffer_id; shared_buffer->m_pid1_region = allocate_region_with_vmo(LinearAddress(), shared_buffer->size(), shared_buffer->m_vmo.copy_ref(), 0, "SharedBuffer", true, true); shared_buffer->m_pid1_region->set_shared(true); *buffer = shared_buffer->m_pid1_region->laddr().as_ptr(); @@ -2491,7 +2494,7 @@ int Process::sys$release_shared_buffer(int shared_buffer_id) return -EINVAL; auto& shared_buffer = *(*it).value; #ifdef SHARED_BUFFER_DEBUG - dbgprintf("%s(%u): Releasing shared buffer %d\n", name().characters(), pid(), shared_buffer_id); + dbgprintf("%s(%u): Releasing shared buffer %d, buffer count: %u\n", name().characters(), pid(), shared_buffer_id, shared_buffers().resource().size()); #endif shared_buffer.release(*this); return 0; @@ -2507,7 +2510,7 @@ void* Process::sys$get_shared_buffer(int shared_buffer_id) if (shared_buffer.pid1() != m_pid && shared_buffer.pid2() != m_pid) return (void*)-EINVAL; #ifdef SHARED_BUFFER_DEBUG - dbgprintf("%s(%u): Retaining shared buffer %d\n", name().characters(), pid(), shared_buffer_id); + dbgprintf("%s(%u): Retaining shared buffer %d, buffer count: %u\n", name().characters(), pid(), shared_buffer_id, shared_buffers().resource().size()); #endif return shared_buffer.retain(*this); } diff --git a/LibGUI/GEventLoop.cpp b/LibGUI/GEventLoop.cpp index 538d1644fe..9c582e83b9 100644 --- a/LibGUI/GEventLoop.cpp +++ b/LibGUI/GEventLoop.cpp @@ -121,6 +121,11 @@ void GEventLoop::handle_paint_event(const WSAPI_ServerMessage& event, GWindow& w post_event(&window, make(event.paint.rect)); } +void GEventLoop::handle_resize_event(const WSAPI_ServerMessage& event, GWindow& window) +{ + post_event(&window, make(event.window.old_rect.size, event.window.rect.size)); +} + void GEventLoop::handle_window_activation_event(const WSAPI_ServerMessage& event, GWindow& window) { #ifdef GEVENTLOOP_DEBUG @@ -303,6 +308,9 @@ void GEventLoop::wait_for_event() case WSAPI_ServerMessage::Type::WindowLeft: handle_window_entered_or_left_event(event, *window); break; + case WSAPI_ServerMessage::Type::WindowResized: + handle_resize_event(event, *window); + break; default: break; } diff --git a/LibGUI/GEventLoop.h b/LibGUI/GEventLoop.h index 9435018f81..881d253eb6 100644 --- a/LibGUI/GEventLoop.h +++ b/LibGUI/GEventLoop.h @@ -43,6 +43,7 @@ private: void wait_for_event(); bool drain_messages_from_server(); void handle_paint_event(const WSAPI_ServerMessage&, GWindow&); + void handle_resize_event(const WSAPI_ServerMessage&, GWindow&); void handle_mouse_event(const WSAPI_ServerMessage&, GWindow&); void handle_key_event(const WSAPI_ServerMessage&, GWindow&); void handle_window_activation_event(const WSAPI_ServerMessage&, GWindow&); diff --git a/LibGUI/GWindow.cpp b/LibGUI/GWindow.cpp index 53a0f9a0db..0234277af2 100644 --- a/LibGUI/GWindow.cpp +++ b/LibGUI/GWindow.cpp @@ -209,6 +209,13 @@ void GWindow::event(GEvent& event) return; } + if (event.type() == GEvent::Resize) { + m_pending_paint_event_rects.clear(); + m_rect_when_windowless = { { }, static_cast(event).size() }; + m_main_widget->set_relative_rect({ { }, static_cast(event).size() }); + return; + } + GObject::event(event); } diff --git a/WindowServer/WSAPITypes.h b/WindowServer/WSAPITypes.h index 8be470a257..0426647ce0 100644 --- a/WindowServer/WSAPITypes.h +++ b/WindowServer/WSAPITypes.h @@ -68,6 +68,7 @@ struct WSAPI_ServerMessage { KeyUp, WindowActivated, WindowDeactivated, + WindowResized, WindowCloseRequest, MenuItemActivated, DidCreateMenubar, @@ -92,6 +93,7 @@ struct WSAPI_ServerMessage { union { struct { WSAPI_Rect rect; + WSAPI_Rect old_rect; } window; struct { WSAPI_Rect rect; diff --git a/WindowServer/WSMessage.h b/WindowServer/WSMessage.h index 3e4f236c70..e256f5be44 100644 --- a/WindowServer/WSMessage.h +++ b/WindowServer/WSMessage.h @@ -21,6 +21,7 @@ public: WindowActivated, WindowDeactivated, WindowCloseRequest, + WindowResized, __Begin_API_Client_Requests, APICreateMenubarRequest, @@ -451,3 +452,20 @@ private: unsigned m_buttons { 0 }; MouseButton m_button { MouseButton::None }; }; + +class WSResizeEvent final : public WSMessage { +public: + WSResizeEvent(const Rect& old_rect, const Rect& rect) + : WSMessage(WSMessage::WindowResized) + , m_old_rect(old_rect) + , m_rect(rect) + { + } + + Rect old_rect() const { return m_old_rect; } + Rect rect() const { return m_rect; } + +private: + Rect m_old_rect; + Rect m_rect; +}; diff --git a/WindowServer/WSWindow.cpp b/WindowServer/WSWindow.cpp index 5c74b0899a..7883de59d8 100644 --- a/WindowServer/WSWindow.cpp +++ b/WindowServer/WSWindow.cpp @@ -48,7 +48,6 @@ void WSWindow::set_rect(const Rect& rect) else if (m_client) { m_backing = m_client->create_shared_bitmap(m_has_alpha_channel ? GraphicsBitmap::Format::RGBA32 : GraphicsBitmap::Format::RGB32, m_rect.size()); } - } WSWindowManager::the().notify_rect_changed(*this, old_rect, rect); } @@ -125,6 +124,11 @@ void WSWindow::on_message(WSMessage& message) case WSMessage::WindowCloseRequest: server_message.type = WSAPI_ServerMessage::Type::WindowCloseRequest; break; + case WSMessage::WindowResized: + server_message.type = WSAPI_ServerMessage::Type::WindowResized; + server_message.window.old_rect = static_cast(message).old_rect(); + server_message.window.rect = static_cast(message).rect(); + break; default: break; } diff --git a/WindowServer/WSWindow.h b/WindowServer/WSWindow.h index 3cb02b5a35..f2ca9980ee 100644 --- a/WindowServer/WSWindow.h +++ b/WindowServer/WSWindow.h @@ -40,6 +40,7 @@ public: void set_rect(const Rect&); void set_rect(int x, int y, int width, int height) { set_rect({ x, y, width, height }); } void set_rect_without_repaint(const Rect& rect) { m_rect = rect; } + void set_rect_from_window_manager_resize(const Rect&); void move_to(const Point& position) { set_rect({ position, size() }); } void move_to(int x, int y) { move_to({ x, y }); } @@ -54,9 +55,6 @@ public: virtual void on_message(WSMessage&) override; - bool is_being_dragged() const { return m_is_being_dragged; } - void set_is_being_dragged(bool b) { m_is_being_dragged = b; } - GraphicsBitmap* backing() { return m_backing.ptr(); } void set_global_cursor_tracking_enabled(bool); @@ -75,7 +73,6 @@ private: String m_title; Rect m_rect; WSWindowType m_type { WSWindowType::Normal }; - bool m_is_being_dragged { false }; bool m_global_cursor_tracking_enabled { false }; bool m_visible { true }; bool m_has_alpha_channel { false }; diff --git a/WindowServer/WSWindowManager.cpp b/WindowServer/WSWindowManager.cpp index c4c97a8cb7..c8beefc03b 100644 --- a/WindowServer/WSWindowManager.cpp +++ b/WindowServer/WSWindowManager.cpp @@ -21,6 +21,7 @@ //#define DEBUG_COUNTERS //#define DEBUG_WID_IN_TITLE_BAR +#define RESIZE_DEBUG static const int window_titlebar_height = 16; @@ -472,7 +473,6 @@ void WSWindowManager::handle_titlebar_mouse_event(WSWindow& window, WSMouseEvent m_drag_window = window.make_weak_ptr();; m_drag_origin = event.position(); m_drag_window_origin = window.position(); - window.set_is_being_dragged(true); invalidate(window); return; } @@ -487,6 +487,17 @@ void WSWindowManager::handle_close_button_mouse_event(WSWindow& window, WSMouseE } } +void WSWindowManager::start_window_resize(WSWindow& window, WSMouseEvent& event) +{ +#ifdef RESIZE_DEBUG + printf("[WM] Begin resizing WSWindow{%p}\n", &window); +#endif + m_resize_window = window.make_weak_ptr();; + m_resize_origin = event.position(); + m_resize_window_original_rect = window.rect(); + invalidate(window); +} + void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& event_window) { event_window = nullptr; @@ -497,7 +508,6 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& event_ printf("[WM] Finish dragging WSWindow{%p}\n", m_drag_window.ptr()); #endif invalidate(*m_drag_window); - m_drag_window->set_is_being_dragged(false); m_drag_window = nullptr; return; } @@ -516,6 +526,38 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& event_ } } + if (m_resize_window) { + if (event.type() == WSMessage::MouseUp && event.button() == MouseButton::Right) { +#ifdef RESIZE_DEBUG + printf("[WM] Finish resizing WSWindow{%p}\n", m_resize_window.ptr()); +#endif + invalidate(*m_resize_window); + m_resize_window = nullptr; + return; + } + + if (event.type() == WSMessage::MouseMove) { + auto old_rect = m_resize_window->rect(); + int dx = event.x() - m_resize_origin.x(); + int dy = event.y() - m_resize_origin.y(); + auto new_rect = m_resize_window_original_rect; + new_rect.set_width(new_rect.width() + dx); + new_rect.set_height(new_rect.height() + dy); +#ifdef RESIZE_DEBUG + dbgprintf("[WM] Resizing [original: %s] now: %s\n", + m_resize_window_original_rect.to_string().characters(), + new_rect.to_string().characters()); +#endif + if (new_rect.width() < 50) + new_rect.set_width(50); + if (new_rect.height() < 50) + new_rect.set_height(50); + m_resize_window->set_rect(new_rect); + WSMessageLoop::the().post_message(m_resize_window.ptr(), make(old_rect, new_rect)); + return; + } + } + for (auto* window = m_windows_in_order.tail(); window; window = window->prev()) { if (!window->global_cursor_tracking()) continue; @@ -559,6 +601,10 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& event_ move_to_front(window); set_active_window(&window); } + if (event.type() == WSMessage::MouseDown && event.button() == MouseButton::Right) { + start_window_resize(window, event); + return IterationDecision::Abort; + } event_window = &window; // FIXME: Should we just alter the coordinates of the existing MouseEvent and pass it through? Point position { event.x() - window.rect().x(), event.y() - window.rect().y() }; diff --git a/WindowServer/WSWindowManager.h b/WindowServer/WSWindowManager.h index 70129010cc..cacc113b0e 100644 --- a/WindowServer/WSWindowManager.h +++ b/WindowServer/WSWindowManager.h @@ -23,6 +23,7 @@ class CharacterBitmap; class GraphicsBitmap; enum class IterationDecision { Continue, Abort }; +enum class ResizeDirection { None, Left, UpLeft, Up, UpRight, Right, DownRight, Down, DownLeft }; class WSWindowManager : public WSMessageReceiver { public: @@ -76,6 +77,7 @@ private: void handle_menubar_mouse_event(WSMouseEvent&); void handle_titlebar_mouse_event(WSWindow&, WSMouseEvent&); void handle_close_button_mouse_event(WSWindow&, WSMouseEvent&); + void start_window_resize(WSWindow&, WSMouseEvent&); void handle_client_request(WSAPIClientRequest&); void set_active_window(WSWindow*); @@ -113,11 +115,16 @@ private: WeakPtr m_active_window; WeakPtr m_hovered_window; - WeakPtr m_drag_window; + WeakPtr m_drag_window; Point m_drag_origin; Point m_drag_window_origin; + WeakPtr m_resize_window; + Rect m_resize_window_original_rect; + Point m_resize_origin; + ResizeDirection m_resize_direction { ResizeDirection::None }; + Rect m_last_cursor_rect; unsigned m_compose_count { 0 };