make window respond to events and lay more groundwork

This commit is contained in:
hippoz 2022-03-09 03:46:27 +02:00
parent 2cc5e1c1e0
commit b4cfe309f3
Signed by: hippoz
GPG key ID: 7C52899193467641
10 changed files with 135 additions and 37 deletions

View file

@ -1,16 +1,15 @@
project('blit', 'cpp') project('raven', 'cpp')
cairomm_dep = dependency('cairomm-1.0') cairomm_dep = dependency('cairomm-1.0')
pangocairo_dep = dependency('pangocairo') pangocairo_dep = dependency('pangocairo')
xlib_dep = dependency('x11') xlib_dep = dependency('x11')
executable( executable(
'blit_app', 'ravenapp',
'./src/Box.cpp', './src/Box.cpp',
'./src/Point.cpp',
'./src/Events.cpp', './src/Events.cpp',
'./src/Widget.cpp', './src/Widget.cpp',
'./src/Painter.cpp',
'./src/Window.cpp', './src/Window.cpp',
'./src/main.cpp', './src/main.cpp',
dependencies : [cairomm_dep, xlib_dep, pangocairo_dep] dependencies : [cairomm_dep, xlib_dep, pangocairo_dep]

View file

@ -1,13 +1,16 @@
#pragma once
#include <stdint.h> #include <stdint.h>
#include "Point.hpp" #include "Point.hpp"
namespace Raven { namespace Raven {
enum class EventType { enum class EventType {
None, NoneEvent,
MouseButton, MouseButton,
MouseMove MouseMove,
WidgetRepaintRequested
}; };
class Event { class Event {
@ -18,8 +21,10 @@ public:
void accept() { m_accepted = true; } void accept() { m_accepted = true; }
bool is_accepted() { return m_accepted; } bool is_accepted() { return m_accepted; }
virtual EventType get_event_type() { return EventType::None; } virtual EventType get_type() { return EventType::NoneEvent; }
virtual const char *get_event_name() { return "None"; } virtual const char *get_name() { return "NoneEvent"; }
virtual ~Event() = default;
}; };
class MouseButtonEvent : public Event { class MouseButtonEvent : public Event {
@ -31,8 +36,8 @@ public:
: m_was_left_button_pressed(was_left_button_pressed) : m_was_left_button_pressed(was_left_button_pressed)
, m_was_right_button_pressed(was_right_button_pressed) {} , m_was_right_button_pressed(was_right_button_pressed) {}
EventType get_event_type() { return EventType::MouseButton; } EventType get_type() { return EventType::MouseButton; }
const char *get_event_name() { return "MouseButton"; } const char *get_name() { return "MouseButton"; }
bool get_was_left_button_pressed() { return m_was_left_button_pressed; } bool get_was_left_button_pressed() { return m_was_left_button_pressed; }
bool get_was_right_button_pressed() { return m_was_right_button_pressed; } bool get_was_right_button_pressed() { return m_was_right_button_pressed; }
@ -45,10 +50,18 @@ public:
MouseMoveEvent(Point point) MouseMoveEvent(Point point)
: m_point(point) {} : m_point(point) {}
EventType get_event_type() { return EventType::MouseMove; } EventType get_type() { return EventType::MouseMove; }
const char *get_event_name() { return "MouseMove"; } const char *get_name() { return "MouseMove"; }
Point &get_point() { return m_point; } Point &get_point() { return m_point; }
}; };
class WidgetRepaintRequestedEvent : public Event {
public:
WidgetRepaintRequestedEvent() {}
EventType get_type() { return EventType::WidgetRepaintRequested; }
const char *get_name() { return "WidgetRepaintRequested"; }
};
} }

View file

@ -1,9 +1,17 @@
#pragma once
#include <cairomm/cairomm.h>
namespace Raven { namespace Raven {
class Painter { class Painter {
Painter() { private:
Cairo::RefPtr<Cairo::Context> m_cairo;
public:
Painter() {}
} Cairo::RefPtr<Cairo::Context> get_cairo() { return m_cairo; }
void set_cairo(Cairo::RefPtr<Cairo::Context> cairo) { m_cairo = cairo; }
}; };
} }

View file

View file

@ -1,3 +1,5 @@
#pragma once
#include <stdint.h> #include <stdint.h>
namespace Raven { namespace Raven {

View file

@ -0,0 +1,31 @@
#include <iostream>
#include "Widget.hpp"
#include "Events.hpp"
namespace Raven {
void Widget::dispatch_event(Event &event) {
process_event(event);
}
void Widget::process_event(Event &event) {
switch (event.get_type()) {
case EventType::MouseMove: {
on_mouse_move(reinterpret_cast<MouseMoveEvent&>(event));
break;
}
case EventType::MouseButton: {
on_mouse_button(reinterpret_cast<MouseButtonEvent&>(event));
break;
}
case EventType::WidgetRepaintRequested: {
on_paint();
break;
}
case EventType::NoneEvent: {
break;
}
}
}
}

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "Box.hpp" #include "Box.hpp"
#include "Events.hpp"
namespace Raven { namespace Raven {
@ -13,6 +14,16 @@ public:
} }
const Box &get_current_geometry() const { return m_current_geometry; } const Box &get_current_geometry() const { return m_current_geometry; }
void dispatch_event(Event &event);
virtual void on_mouse_button(MouseButtonEvent &event) = 0;
virtual void on_mouse_move(MouseMoveEvent &event) = 0;
virtual void on_paint() = 0;
virtual ~Widget() = default;
private:
void process_event(Event &event);
}; };
} }

View file

@ -1,37 +1,63 @@
#include <X11/X.h>
#include <iostream> #include <iostream>
#include "Window.hpp" #include "Window.hpp"
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <cairomm-1.0/cairomm/cairomm.h> #include <X11/Xutil.h>
#include <cairomm-1.0/cairomm/context.h> #include <cairomm/cairomm.h>
#include <cairomm-1.0/cairomm/surface.h> #include <cairomm/context.h>
#include <cairomm-1.0/cairomm/xlib_surface.h> #include <cairomm/surface.h>
#include <cairomm/xlib_surface.h>
namespace Raven { namespace Raven {
bool Window::spawn_window() { bool Window::spawn_window() {
Display *dsp; Display *dsp = XOpenDisplay(NULL);
Drawable da; if (dsp == NULL) {
int screen;
if ((dsp = XOpenDisplay(NULL)) == NULL) {
std::cout << "error: XOpenDisplay(NULL)" << "\n"; std::cout << "error: XOpenDisplay(NULL)" << "\n";
return false; return false;
} }
m_x_display = dsp;
screen = DefaultScreen(dsp); int screen = DefaultScreen(dsp);
da = XCreateSimpleWindow(dsp, DefaultRootWindow(dsp), 0, 0, get_current_geometry().get_width(), get_current_geometry().get_height(), 0, 0, 0); Drawable da = XCreateSimpleWindow(dsp, DefaultRootWindow(dsp), 0, 0, m_current_geometry.get_width(), m_current_geometry.get_height(), 0, 0, 0);
XSelectInput(dsp, da, ButtonPressMask | ButtonReleaseMask | KeyPressMask | PointerMotionMask);
XSelectInput(dsp, da, ButtonPressMask | ButtonReleaseMask | KeyPressMask | PointerMotionMask | StructureNotifyMask | ExposureMask);
XMapWindow(dsp, da); XMapWindow(dsp, da);
auto x_surface = Cairo::XlibSurface::create(
auto cairo_xlib_surface = Cairo::XlibSurface::create(
dsp, dsp,
da, da,
DefaultVisual(dsp, screen), DefaultVisual(dsp, screen),
get_current_geometry().get_width(), get_current_geometry().get_width(),
get_current_geometry().get_height() get_current_geometry().get_height()
); );
Cairo::Context::create(x_surface); auto cairo_context = Cairo::Context::create(cairo_xlib_surface);
m_painter.set_cairo(cairo_context);
return true; return true;
} }
void Window::run(bool block) {
XEvent e;
for (;;) {
if (block || XPending(m_x_display))
XNextEvent(m_x_display, &e);
else
break;
switch (e.type) {
case MapNotify: {
std::cout << "MapNotify\n";
break;
}
case Expose: {
std::cout << "we'd probably repaint the window right now\n";
break;
}
}
}
}
} }

View file

@ -1,4 +1,8 @@
#pragma once
#include "Widget.hpp" #include "Widget.hpp"
#include "Painter.hpp"
#include <X11/Xlib.h>
namespace Raven { namespace Raven {
@ -6,17 +10,21 @@ class Window {
private: private:
Widget *m_active_widget { nullptr }; Widget *m_active_widget { nullptr };
Box m_current_geometry { 0, 0, 800, 600 }; Box m_current_geometry { 0, 0, 800, 600 };
public: Painter m_painter {};
Window() {
} Display *m_x_display { nullptr };
public:
Window() {}
Painter &get_painter() { return m_painter; }
Widget *get_active_widget() { return m_active_widget; } Widget *get_active_widget() { return m_active_widget; }
void set_active_widget(Widget *active_widget) { m_active_widget = active_widget; } void set_active_widget(Widget *active_widget) { m_active_widget = active_widget; }
Box &get_current_geometry() { return m_current_geometry; } Box &get_current_geometry() { return m_current_geometry; }
bool spawn_window(); bool spawn_window();
void window_event_loop(); void run(bool block);
}; };
} }

View file

@ -2,10 +2,10 @@
#include "Window.hpp" #include "Window.hpp"
int main() { int main() {
Raven::Window window{}; Raven::Window window {};
window.spawn_window(); window.spawn_window();
for(;;){} window.run(true);
return 0; return 0;
} }