summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/window/.nix/derivation.nix1
-rw-r--r--src/window/SConstruct4
-rw-r--r--src/window/device.h22
-rw-r--r--src/window/old.dummy (renamed from src/window/old.cpp)0
-rw-r--r--src/window/window.h14
-rw-r--r--src/window/xcb.cpp89
-rw-r--r--src/window/xcb.h23
-rw-r--r--tests/window.cpp8
8 files changed, 103 insertions, 58 deletions
diff --git a/src/window/.nix/derivation.nix b/src/window/.nix/derivation.nix
index 77189f1..9974564 100644
--- a/src/window/.nix/derivation.nix
+++ b/src/window/.nix/derivation.nix
@@ -27,6 +27,7 @@ in stdenvNoCC.mkDerivation {
forstio.core
forstio.async
forstio.io
+ forstio.codec
xorg.libX11
xorg.libxcb
];
diff --git a/src/window/SConstruct b/src/window/SConstruct
index 69c70eb..05fc016 100644
--- a/src/window/SConstruct
+++ b/src/window/SConstruct
@@ -44,9 +44,9 @@ env_vars.Add('prefix',
)
env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[],
- CPPDEFINES=['SAW_UNIX'],
+ CPPDEFINES=['SAW_UNIX', 'SAW_UNIX_XCB'],
CXXFLAGS=['-std=c++20','-g','-Wall','-Wextra'],
- LIBS=['forstio-core', 'forstio-io', 'forstio-async'])
+ LIBS=['forstio-core', 'forstio-io', 'forstio-async', 'forstio-codec'])
env.__class__.add_source_files = add_kel_source_files
env.Tool('compilation_db');
env.cdb = env.CompilationDatabase('compile_commands.json');
diff --git a/src/window/device.h b/src/window/device.h
index c547da2..7d3cdb1 100644
--- a/src/window/device.h
+++ b/src/window/device.h
@@ -1,32 +1,18 @@
#pragma once
+#include "window.h"
+
#include <forstio/async/async.h>
#include <forstio/core/common.h>
+#include <forstio/codec/data.h>
+#include <forstio/io/io.h>
#include <string_view>
#include <variant>
-#include "window.h"
-
namespace saw {
namespace gfx {
template<typename T>
class device;
}
-/**
-namespace saw {
-class device {
-public:
- virtual ~device() = default;
-
- virtual own<window> create_window(const video_mode &mode,
- std::string_view title_view) = 0;
- virtual void flush() = 0;
-};
-
-class io_provider;
-own<device> create_device(io_provider &provider);
-} // namespace saw
-*/
-}
}
diff --git a/src/window/old.cpp b/src/window/old.dummy
index c762945..c762945 100644
--- a/src/window/old.cpp
+++ b/src/window/old.dummy
diff --git a/src/window/window.h b/src/window/window.h
index 716b25d..36786de 100644
--- a/src/window/window.h
+++ b/src/window/window.h
@@ -1,5 +1,7 @@
#pragma once
+#include "video_mode.h"
+
#include <forstio/async/async.h>
#include <forstio/core/common.h>
#include <forstio/codec/schema.h>
@@ -7,10 +9,10 @@
#include <string_view>
#include <variant>
-#include "video_mode.h"
-
namespace saw {
+namespace gfx {
namespace schema {
+using namespace saw::schema;
using WindowResize = Struct<
Member<UInt32, "width">,
Member<UInt32, "height">
@@ -19,11 +21,13 @@ using WindowEvents = Union<
Member<WindowResize, "resize">
>;
}
+
+template<typename T>
+class window;
+}
}
-#ifdef SAW_UNIX_XCB
-#include "xcb.h"
-#endif
+#include "linux_xcb.h"
/**
namespace saw {
diff --git a/src/window/xcb.cpp b/src/window/xcb.cpp
index e08291f..62f8182 100644
--- a/src/window/xcb.cpp
+++ b/src/window/xcb.cpp
@@ -5,12 +5,12 @@
#include "xcb.h"
namespace saw {
+namespace gfx {
device<backend::linux_xcb>::device(::Display* disp, int screen, xcb_connection_t *xcb_connection, xcb_screen_t *xcb_screen, own<input_stream>&& an):
display_{disp}, screen_{screen}, xcb_connection_{xcb_connection}, xcb_screen_{xcb_screen}, async_notifier_{std::move(an)},
- async_conveyor_{async_notifier->read_ready()
+ async_conveyor_{async_notifier_->read_ready()
.then([this]() { handle_events(); })
.sink()} {}
-{}
device<backend::linux_xcb>::~device(){
if (display_) {
@@ -24,8 +24,8 @@ void device<backend::linux_xcb>::xcb_window_was_destroyed(xcb_window_t window_id
}
void device<backend::linux_xcb>::handle_events(){
- while (xcb_generic_event_t *event = xcb_poll_for_event(xcb_connection)) {
- pending_events.push_back(event);
+ while (xcb_generic_event_t *event = xcb_poll_for_event(xcb_connection_)) {
+ pending_events_.push_back(event);
}
for (size_t i = 0; i < pending_events_.size(); ++i) {
xcb_generic_event_t *event = pending_events_.at(i);
@@ -33,8 +33,8 @@ void device<backend::linux_xcb>::handle_events(){
case XCB_MOTION_NOTIFY: {
xcb_motion_notify_event_t *motion =
reinterpret_cast<xcb_motion_notify_event_t *>(event);
- auto find = windows.find(motion->event);
- if (find != windows.end()) {
+ auto find = windows_.find(motion->event);
+ if (find != windows_.end()) {
assert(find->second);
find->second->mouse_move_event(motion->event_x,
motion->event_y);
@@ -43,8 +43,8 @@ void device<backend::linux_xcb>::handle_events(){
case XCB_EXPOSE: {
xcb_expose_event_t *expose =
reinterpret_cast<xcb_expose_event_t *>(event);
- auto find = windows.find(expose->window);
- if (find != windows.end()) {
+ auto find = windows_.find(expose->window);
+ if (find != windows_.end()) {
assert(find->second);
find->second->resize_event(static_cast<size_t>(expose->x),
static_cast<size_t>(expose->y),
@@ -55,8 +55,8 @@ void device<backend::linux_xcb>::handle_events(){
case XCB_BUTTON_RELEASE: {
xcb_button_release_event_t *button =
reinterpret_cast<xcb_button_release_event_t *>(event);
- auto find = windows.find(button->event);
- if (find != windows.end()) {
+ auto find = windows_.find(button->event);
+ if (find != windows_.end()) {
assert(find->second);
find->second->mouse_event(button->event_x, button->event_y,
button->detail, false);
@@ -65,8 +65,8 @@ void device<backend::linux_xcb>::handle_events(){
case XCB_BUTTON_PRESS: {
xcb_button_press_event_t *button =
reinterpret_cast<xcb_button_press_event_t *>(event);
- auto find = windows.find(button->event);
- if (find != windows.end()) {
+ auto find = windows_.find(button->event);
+ if (find != windows_.end()) {
assert(find->second);
find->second->mouse_event(button->event_x, button->event_y,
button->detail, true);
@@ -80,8 +80,8 @@ void device<backend::linux_xcb>::handle_events(){
/*
* Peek into future events
*/
- for (size_t j = i + 1; j < pending_events.size(); ++j) {
- xcb_generic_event_t *f_ev = pending_events.at(j);
+ for (size_t j = i + 1; j < pending_events_.size(); ++j) {
+ xcb_generic_event_t *f_ev = pending_events_.at(j);
if ((f_ev->response_type & ~0x80) == XCB_KEY_PRESS) {
xcb_key_press_event_t *f_key =
@@ -89,18 +89,18 @@ void device<backend::linux_xcb>::handle_events(){
if (key->detail == f_key->detail &&
key->event == f_key->event) {
- auto iterator = pending_events.begin() + j;
- assert(iterator != pending_events.end());
+ auto iterator = pending_events_.begin() + j;
+ assert(iterator != pending_events_.end());
free(*iterator);
- pending_events.erase(iterator);
+ pending_events_.erase(iterator);
repeat = true;
break;
}
}
}
- auto find = windows.find(key->event);
- if (find != windows.end()) {
+ auto find = windows_.find(key->event);
+ if (find != windows_.end()) {
assert(find->second);
find->second->keyboard_event(key->event_x, key->event_y,
key->detail, repeat, repeat);
@@ -109,8 +109,8 @@ void device<backend::linux_xcb>::handle_events(){
case XCB_KEY_PRESS: {
xcb_key_press_event_t *key =
reinterpret_cast<xcb_key_press_event_t *>(event);
- auto find = windows.find(key->event);
- if (find != windows.end()) {
+ auto find = windows_.find(key->event);
+ if (find != windows_.end()) {
assert(find->second);
find->second->keyboard_event(key->event_x, key->event_y,
key->detail, true, false);
@@ -127,7 +127,45 @@ void device<backend::linux_xcb>::handle_events(){
pending_events_.clear();
}
-own<window> device<backend::linux_xcb>::create_window(const video_mode& vid_mode, std::string_view title_view){
+own<window<backend::linux_xcb>> device<backend::linux_xcb>::create_xcb_window(const video_mode &vid_mode,
+ std::string_view title_view,
+ int visual_id) {
+ assert(xcb_screen_);
+ assert(xcb_connection_);
+
+ xcb_colormap_t xcb_colormap = xcb_generate_id(xcb_connection_);
+ xcb_window_t xcb_window = xcb_generate_id(xcb_connection_);
+
+ xcb_create_colormap(xcb_connection_, XCB_COLORMAP_ALLOC_NONE, xcb_colormap,
+ xcb_screen_->root, visual_id);
+
+ uint32_t eventmask =
+ XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS |
+ XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS |
+ XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION |
+ XCB_EVENT_MASK_BUTTON_MOTION;
+ uint32_t valuelist[] = {eventmask, xcb_colormap, 0};
+ uint32_t valuemask = XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;
+
+ xcb_create_window(xcb_connection_, XCB_COPY_FROM_PARENT, xcb_window,
+ xcb_screen_->root, 0, 0, vid_mode.width,
+ vid_mode.height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
+ visual_id, valuemask, valuelist);
+
+ xcb_change_property(xcb_connection_, XCB_PROP_MODE_REPLACE, xcb_window,
+ XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, title_view.size(),
+ title_view.data());
+
+ xcb_flush(xcb_connection_);
+ auto win = heap<window<backend::linux_xcb>>(*this, xcb_window, xcb_colormap,
+ vid_mode, title_view);
+ // Insert into map
+ windows_[xcb_window] = win.get();
+
+ return win;
+}
+
+own<window<backend::linux_xcb>> device<backend::linux_xcb>::create_window(const video_mode& vid_mode, std::string_view title_view){
assert(xcb_screen_);
return create_xcb_window(vid_mode, title_view, xcb_screen_->root_visual);
}
@@ -137,7 +175,7 @@ void device<backend::linux_xcb>::flush(){
xcb_flush(xcb_connection_);
}
-error_or<own<device<backend::linux_xcb>>> create_xcb_device(){
+error_or<own<device<backend::linux_xcb>>> create_xcb_device(io_provider& provider){
::Display *display = ::XOpenDisplay(nullptr);
if (!display) {
/// @todo log errors
@@ -174,12 +212,12 @@ error_or<own<device<backend::linux_xcb>>> create_xcb_device(){
return heap<device<backend::linux_xcb>>(display, screen, xcb_connection, xcb_screen, std::move(fd_wrapped));
}
-window<backend::linux_xcb>::window(device& dev_, xcb_window_t xcb_win, xcb_colormap_t xcb_colormap_, const video_mode& vid_mode_, std::string_view& title_view):
+window<backend::linux_xcb>::window(device<backend::linux_xcb>& dev_, xcb_window_t xcb_win, xcb_colormap_t xcb_colormap_, const video_mode& vid_mode_, std::string_view& title_view_):
device_{&dev_},
xcb_window_{xcb_win},
xcb_colormap_{xcb_colormap_},
video_mode_{vid_mode_},
- window_title_{tile_view_}
+ window_title_{title_view_}
{
// TODO
}
@@ -197,3 +235,4 @@ void window<backend::linux_xcb>::hide(){
}
}
+}
diff --git a/src/window/xcb.h b/src/window/xcb.h
index e2928b6..53aac5f 100644
--- a/src/window/xcb.h
+++ b/src/window/xcb.h
@@ -6,11 +6,15 @@
#include "backends.h"
#include "device.h"
+#include "window.h"
+
+#include <map>
+
+#include <X11/Xlib-xcb.h>
+#include <X11/Xlib.h>
namespace saw {
namespace gfx {
-class window;
-
template<>
class device<backend::linux_xcb> final {
private:
@@ -23,9 +27,11 @@ private:
own<input_stream> async_notifier_;
conveyor_sink async_conveyor_;
- std::map<xcb_window_t, window *> windows_;
+ std::map<xcb_window_t, window<backend::linux_xcb> *> windows_;
std::vector<xcb_generic_event_t *> pending_events_;
+private:
+ own<window<backend::linux_xcb>> create_xcb_window(const video_mode& vid_mod, std::string_view title_view, int visual_id);
public:
device(::Display *display, int screen, xcb_connection_t *xcb_connection,
xcb_screen_t *xcb_screen, own<input_stream> && an);
@@ -35,16 +41,17 @@ public:
void xcb_window_was_destroyed(xcb_window_t window_id);
void handle_events();
- window<backend::linux_xcb> create_window(const video_mode& vid_mod, std::string_view title_view);
+ own<window<backend::linux_xcb>> create_window(const video_mode& vid_mod, std::string_view title_view);
void flush();
};
-error_or<device<backend::linux_xcb>> create_xcb_device();
+error_or<own<device<backend::linux_xcb>>> create_xcb_device(io_provider& provider);
-class window {
+template<>
+class window<backend::linux_xcb> final {
private:
- device *device_;
+ device<backend::linux_xcb> *device_;
xcb_window_t xcb_window_;
xcb_colormap_t xcb_colormap_;
@@ -54,7 +61,7 @@ private:
own<conveyor_feeder<data<schema::WindowEvents>>> event_feeder = nullptr;
public:
- window(device& dev_, xcb_window_t xcb_win, xcb_colormap_t xcb_colormap_, const video_mode& vid_mode_, std::string_view title_view_);
+ window(device<backend::linux_xcb>& dev_, xcb_window_t xcb_win, xcb_colormap_t xcb_colormap_, const video_mode& vid_mode_, std::string_view title_view_);
~window();
diff --git a/tests/window.cpp b/tests/window.cpp
new file mode 100644
index 0000000..f3db43f
--- /dev/null
+++ b/tests/window.cpp
@@ -0,0 +1,8 @@
+#include <forstio/test/suite.h>
+#include <forstio/window/device.h>
+
+namespace {
+SAW_TEST("Device creation") {
+
+}
+}