Browse Source

Build Painter & friends into LibC. Use it in the GUI test app.

Andreas Kling 6 năm trước cách đây
mục cha
commit
b673c1a77d

+ 2 - 0
Kernel/ProcessGUI.cpp

@@ -111,6 +111,8 @@ int Process::gui$invalidate_window(int window_id)
     if (it == m_windows.end())
         return -EBADWINDOW;
     auto& window = *(*it).value;
+    // FIXME: This should queue up a message that the window server process can read.
+    //        Poking into its data structures is not good.
     WindowManager::the().invalidate(window);
     return 0;
 }

+ 1 - 1
Kernel/kprintf.cpp

@@ -39,7 +39,7 @@ static void debugger_putch(char*&, char ch)
     IO::out8(0xe9, ch);
 }
 
-int dbgprintf(const char* fmt, ...)
+extern "C" int dbgprintf(const char* fmt, ...)
 {
     va_list ap;
     va_start(ap, fmt);

+ 2 - 1
Kernel/kprintf.h

@@ -2,7 +2,8 @@
 
 #include <AK/Compiler.h>
 
+extern "C" {
 int dbgprintf(const char *fmt, ...);
 int kprintf(const char *fmt, ...);
 int ksprintf(char* buf, const char *fmt, ...);
-
+}

+ 5 - 0
LibC/Makefile

@@ -6,6 +6,10 @@ AK_OBJS = \
     ../AK/kmalloc.o
 
 WIDGETS_OBJS = \
+    ../Widgets/Painter.o \
+    ../Widgets/Font.o \
+    ../Widgets/GraphicsBitmap.o \
+    ../Widgets/CharacterBitmap.o \
     ../Widgets/Color.o
 
 LIBC_OBJS = \
@@ -36,6 +40,7 @@ LIBC_OBJS = \
        ioctl.o \
        math.o \
        utime.o \
+       gui.o \
        entry.o
 
 OBJS = $(AK_OBJS) $(WIDGETS_OBJS) $(LIBC_OBJS)

+ 22 - 0
LibC/gui.cpp

@@ -0,0 +1,22 @@
+#include "gui.h"
+#include <Kernel/GUITypes.h>
+#include <Kernel/Syscall.h>
+#include <errno.h>
+
+int gui_create_window(const GUI_CreateWindowParameters* params)
+{
+    int rc = syscall(SC_gui_create_window, params);
+    __RETURN_WITH_ERRNO(rc, rc, -1);
+}
+
+int gui_invalidate_window(int window_id)
+{
+    int rc = syscall(SC_gui_invalidate_window, window_id);
+    __RETURN_WITH_ERRNO(rc, rc, -1);
+}
+
+int gui_get_window_backing_store(int window_id, GUI_WindowBackingStoreInfo* info)
+{
+    int rc = syscall(SC_gui_get_window_backing_store, window_id, info);
+    __RETURN_WITH_ERRNO(rc, rc, -1);
+}

+ 13 - 0
LibC/gui.h

@@ -0,0 +1,13 @@
+#pragma once
+
+#include <sys/cdefs.h>
+#include <Kernel/GUITypes.h>
+
+__BEGIN_DECLS
+
+int gui_create_window(const GUI_CreateWindowParameters* params);
+int gui_invalidate_window(int window_id);
+int gui_get_window_backing_store(int window_id, GUI_WindowBackingStoreInfo* info);
+
+__END_DECLS
+

+ 1 - 1
LibC/stdio.cpp

@@ -230,7 +230,7 @@ static void sys_putch(char*&, char ch)
     syscall(SC_putch, ch);
 }
 
-int sys_printf(const char* fmt, ...)
+int dbgprintf(const char* fmt, ...)
 {
     va_list ap;
     va_start(ap, fmt);

+ 1 - 1
LibC/stdio.h

@@ -54,7 +54,7 @@ int vfprintf(FILE*, const char* fmt, va_list);
 int vsprintf(char* buffer, const char* fmt, va_list);
 int fprintf(FILE*, const char* fmt, ...);
 int printf(const char* fmt, ...);
-int sys_printf(const char* fmt, ...);
+int dbgprintf(const char* fmt, ...);
 int sprintf(char* buffer, const char* fmt, ...);
 int putchar(int ch);
 int putc(int ch, FILE*);

+ 26 - 20
Userland/guitest.cpp

@@ -5,15 +5,12 @@
 #include <stdlib.h>
 #include <fcntl.h>
 #include <assert.h>
-#include <Kernel/GUITypes.h>
 #include <Kernel/Syscall.h>
-#include <AK/StdLibExtras.h>
+#include <Widgets/GraphicsBitmap.h>
+#include <Widgets/Painter.h>
+#include "gui.h"
 
-int gui_invalidate_window(int window_id)
-{
-    int rc = syscall(SC_gui_invalidate_window, window_id);
-    __RETURN_WITH_ERRNO(rc, rc, -1);
-}
+static void paint(GraphicsBitmap& bitmap, int width, int height);
 
 int main(int argc, char** argv)
 {
@@ -21,7 +18,7 @@ int main(int argc, char** argv)
     wparams.rect = { { 200, 200 }, { 300, 200 } };
     wparams.background_color = 0xffc0c0;
     strcpy(wparams.title, "GUI test app");
-    int window_id = syscall(SC_gui_create_window, &wparams);
+    int window_id = gui_create_window(&wparams);
     if (window_id < 0) {
         perror("gui_create_window");
         return 1;
@@ -34,15 +31,17 @@ int main(int argc, char** argv)
     }
 
     GUI_WindowBackingStoreInfo backing;
-    int rc = syscall(SC_gui_get_window_backing_store, window_id, &backing);
+    int rc = gui_get_window_backing_store(window_id, &backing);
     if (rc < 0) {
         perror("gui_get_window_backing_store");
         return 1;
     }
 
-    sys_printf("(Client) window backing %ux%u @ %p\n", backing.size.width, backing.size.height, backing.pixels);
+    auto bitmap = GraphicsBitmap::create_wrapper(backing.size, backing.pixels);
+
+    dbgprintf("(Client) window backing %ux%u @ %p\n", backing.size.width, backing.size.height, backing.pixels);
 
-    fast_dword_fill(backing.pixels, 0x00ff00, backing.size.width * backing.size.height);
+    paint(*bitmap, backing.size.width, backing.size.height);
 
     rc = gui_invalidate_window(window_id);
     if (rc < 0) {
@@ -59,21 +58,28 @@ int main(int argc, char** argv)
         }
         assert(nread == sizeof(event));
         switch (event.type) {
-        case GUI_Event::Type::Paint: sys_printf("WID=%x Paint [%d,%d %dx%d]\n", event.window_id, event.paint.rect.location.x, event.paint.rect.location.y, event.paint.rect.size.width, event.paint.rect.size.height); break;
-        case GUI_Event::Type::MouseDown: sys_printf("WID=%x MouseDown %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
-        case GUI_Event::Type::MouseUp: sys_printf("WID=%x MouseUp %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
-        case GUI_Event::Type::MouseMove: sys_printf("WID=%x MouseMove %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
+        case GUI_Event::Type::Paint: dbgprintf("WID=%x Paint [%d,%d %dx%d]\n", event.window_id, event.paint.rect.location.x, event.paint.rect.location.y, event.paint.rect.size.width, event.paint.rect.size.height); break;
+        case GUI_Event::Type::MouseDown: dbgprintf("WID=%x MouseDown %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
+        case GUI_Event::Type::MouseUp: dbgprintf("WID=%x MouseUp %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
+        case GUI_Event::Type::MouseMove: dbgprintf("WID=%x MouseMove %d,%d\n", event.window_id, event.mouse.position.x, event.mouse.position.y); break;
         }
 
         if (event.type == GUI_Event::Type::MouseDown) {
-            byte r = rand() % 255;
-            byte g = rand() % 255;
-            byte b = rand() % 255;
-            Color color(r, g, b);
-            fast_dword_fill(backing.pixels, color.value(), backing.size.width * backing.size.height);
+            paint(*bitmap, backing.size.width, backing.size.height);
             gui_invalidate_window(window_id);
         }
 
     }
     return 0;
 }
+
+void paint(GraphicsBitmap& bitmap, int width, int height)
+{
+    byte r = rand() % 255;
+    byte g = rand() % 255;
+    byte b = rand() % 255;
+    Color color(r, g, b);
+    Painter painter(bitmap);
+    painter.fill_rect({0, 0, width, height}, color);
+    painter.draw_text({0, 0, width, height}, "Hello World!", Painter::TextAlignment::Center, Color::Black);
+}

+ 12 - 5
Widgets/GraphicsBitmap.cpp

@@ -1,19 +1,18 @@
 #include "GraphicsBitmap.h"
 #include "EventLoop.h"
 #include <AK/kmalloc.h>
+
+#ifdef KERNEL
 #include "Process.h"
 #include "MemoryManager.h"
+#endif
 
+#ifdef KERNEL
 RetainPtr<GraphicsBitmap> GraphicsBitmap::create(Process& process, const Size& size)
 {
     return adopt(*new GraphicsBitmap(process, size));
 }
 
-RetainPtr<GraphicsBitmap> GraphicsBitmap::create_wrapper(const Size& size, RGBA32* data)
-{
-    return adopt(*new GraphicsBitmap(size, data));
-}
-
 GraphicsBitmap::GraphicsBitmap(Process& process, const Size& size)
     : m_size(size)
     , m_pitch(size.width() * sizeof(RGBA32))
@@ -34,6 +33,12 @@ GraphicsBitmap::GraphicsBitmap(Process& process, const Size& size)
     }
     m_data = (RGBA32*)m_server_region->linearAddress.asPtr();
 }
+#endif
+
+RetainPtr<GraphicsBitmap> GraphicsBitmap::create_wrapper(const Size& size, RGBA32* data)
+{
+    return adopt(*new GraphicsBitmap(size, data));
+}
 
 GraphicsBitmap::GraphicsBitmap(const Size& size, RGBA32* data)
     : m_size(size)
@@ -44,10 +49,12 @@ GraphicsBitmap::GraphicsBitmap(const Size& size, RGBA32* data)
 
 GraphicsBitmap::~GraphicsBitmap()
 {
+#ifdef KERNEL
     if (m_client_region)
         m_client_process->deallocate_region(*m_client_region);
     if (m_server_region)
         EventLoop::main().server_process().deallocate_region(*m_server_region);
+#endif
     m_data = nullptr;
 }
 

+ 12 - 0
Widgets/GraphicsBitmap.h

@@ -4,11 +4,16 @@
 #include "Size.h"
 #include <AK/Retainable.h>
 #include <AK/RetainPtr.h>
+
+#ifdef KERNEL
 #include "Process.h"
+#endif
 
 class GraphicsBitmap : public Retainable<GraphicsBitmap> {
 public:
+#ifdef KERNEL
     static RetainPtr<GraphicsBitmap> create(Process&, const Size&);
+#endif
     static RetainPtr<GraphicsBitmap> create_wrapper(const Size&, RGBA32*);
     ~GraphicsBitmap();
 
@@ -20,17 +25,24 @@ public:
     int height() const { return m_size.height(); }
     size_t pitch() const { return m_pitch; }
 
+#ifdef KERNEL
     Region* client_region() { return m_client_region; }
     Region* server_region() { return m_server_region; }
+#endif
 
 private:
+#ifdef KERNEL
     GraphicsBitmap(Process&, const Size&);
+#endif
     GraphicsBitmap(const Size&, RGBA32*);
 
     Size m_size;
     RGBA32* m_data { nullptr };
     size_t m_pitch { 0 };
+
+#ifdef KERNEL
     Process* m_client_process { nullptr };
     Region* m_client_region { nullptr };
     Region* m_server_region { nullptr };
+#endif
 };

+ 2 - 2
Widgets/Painter.cpp

@@ -1,7 +1,7 @@
 #include "Painter.h"
 #include "Widget.h"
 #include "Font.h"
-#include "Window.h"
+#include "GraphicsBitmap.h"
 #include <AK/Assertions.h>
 #include <AK/StdLibExtras.h>
 
@@ -115,7 +115,7 @@ void Painter::draw_text(const Rect& rect, const String& text, TextAlignment alig
             continue;
         auto* bitmap = font().glyphBitmap(ch);
         if (!bitmap) {
-            printf("Font doesn't have 0x%02x ('%c')\n", ch, ch);
+            dbgprintf("Font doesn't have 0x%02x ('%c')\n", ch, ch);
             ASSERT_NOT_REACHED();
         }
         int x = point.x() + i * font().glyphWidth();

+ 1 - 2
Widgets/Widget.cpp

@@ -29,8 +29,7 @@ void Widget::setWindowRelativeRect(const Rect& rect, bool should_update)
 
 void Widget::repaint(const Rect& rect)
 {
-    if (auto* w = window())
-        w->repaint(rect);
+    // FIXME: Implement.
 }
 
 void Widget::event(Event& event)

+ 0 - 10
Widgets/Window.cpp

@@ -37,16 +37,6 @@ void Window::setRect(const Rect& rect)
     WindowManager::the().notifyRectChanged(*this, oldRect, m_rect);
 }
 
-void Window::repaint(const Rect& rect)
-{
-    event(*make<PaintEvent>(rect));
-}
-
-void Window::update(const Rect& rect)
-{
-    EventLoop::main().postEvent(this, make<PaintEvent>(rect));
-}
-
 // FIXME: Just use the same types.
 static GUI_MouseButton to_api(MouseButton button)
 {

+ 0 - 3
Widgets/Window.h

@@ -38,9 +38,6 @@ public:
     bool isBeingDragged() const { return m_isBeingDragged; }
     void setIsBeingDragged(bool b) { m_isBeingDragged = b; }
 
-    void repaint(const Rect& = Rect());
-    void update(const Rect& = Rect());
-
     bool isActive() const;
 
     bool isVisible() const;

+ 5 - 4
Widgets/WindowManager.cpp

@@ -267,7 +267,8 @@ void WindowManager::processMouseEvent(MouseEvent& event)
 
 void WindowManager::compose()
 {
-    printf("[WM] compose #%u (%u rects)\n", ++m_recompose_count, m_invalidated_rects.size());
+    auto invalidated_rects = move(m_invalidated_rects);
+    printf("[WM] compose #%u (%u rects)\n", ++m_recompose_count, invalidated_rects.size());
 
     dbgprintf("kmalloc stats: alloc:%u free:%u eternal:%u\n", sum_alloc, sum_free, kmalloc_sum_eternal);
 
@@ -279,7 +280,7 @@ void WindowManager::compose()
         return false;
     };
 
-    for (auto& r : m_invalidated_rects) {
+    for (auto& r : invalidated_rects) {
         if (any_window_contains_rect(r))
             continue;
         //dbgprintf("Repaint root %d,%d %dx%d\n", r.x(), r.y(), r.width(), r.height());
@@ -291,10 +292,9 @@ void WindowManager::compose()
         paintWindowFrame(*window);
         m_back_painter->blit(window->position(), *window->backing());
     }
-    for (auto& r : m_invalidated_rects)
+    for (auto& r : invalidated_rects)
         flush(r);
     draw_cursor();
-    m_invalidated_rects.clear_with_capacity();
 }
 
 void WindowManager::draw_cursor()
@@ -364,6 +364,7 @@ void WindowManager::invalidate(const Rect& a_rect)
     auto rect = Rect::intersection(a_rect, m_screen_rect);
     if (rect.is_empty())
         return;
+
     for (auto& r : m_invalidated_rects) {
         if (r.contains(rect))
             return;