diff options
-rw-r--r-- | src/window/.nix/derivation.nix | 1 | ||||
-rw-r--r-- | src/window/SConstruct | 4 | ||||
-rw-r--r-- | src/window/device.h | 22 | ||||
-rw-r--r-- | src/window/old.dummy (renamed from src/window/old.cpp) | 0 | ||||
-rw-r--r-- | src/window/window.h | 14 | ||||
-rw-r--r-- | src/window/xcb.cpp | 89 | ||||
-rw-r--r-- | src/window/xcb.h | 23 | ||||
-rw-r--r-- | tests/window.cpp | 8 |
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") { + +} +} |