9 #ifndef zakero_Xenium_h
10 #define zakero_Xenium_h
181 #include <unordered_map>
184 #include <linux/input-event-codes.h>
188 #include <xcb/xcb_icccm.h>
189 #include <xcb/randr.h>
194 #define explicit explicit_
224 #define ZAKERO_XENIUM__ERROR_DATA \
225 X(Error_None , 0 , "No Error" ) \
226 X(Error_Unknown , 1 , "An unknown error has occurred" ) \
227 X(Error_Connection_Failed , 2 , "Failed due to socket, pipe, or other stream errors" ) \
228 X(Error_Extension_Not_Supported , 3 , "The requested XCB extension is not supported" ) \
229 X(Error_Invalid_Display_Name , 4 , "An error occured while parsing the X11 display name" ) \
230 X(Error_Invalid_Screen , 5 , "The X11 server does not have a screen matching the display" ) \
231 X(Error_Minimum_Size_Greater_Than_Maximum_Size , 6 , "The minimum window size is larger than the maximum window size." ) \
232 X(Error_Not_Enough_Memory , 7 , "Insufficient memory" ) \
233 X(Error_Request_Too_Long , 8 , "The request was longer than what is excepted by the X11 server" ) \
234 X(Error_Window_Size_Too_Small , 9 , "The window size was too small." ) \
235 X(Error_RandR_CRTC_Info_Not_Found , 10 , "XCB RandR CRTC Information was not found" ) \
236 X(Error_RandR_Invalid_CRTC_Id , 11 , "XCB RandR CRTC ID is not valid" ) \
237 X(Error_RandR_Invalid_Output_Id , 12 , "XCB RandR Output ID is not valid" ) \
238 X(Error_RandR_Not_Available , 13 , "XCB RandR extenstion is not available" ) \
239 X(Error_RandR_Output_Info_Is_Incomplete , 14 , "XCB RandR Output Information does not have enough data" ) \
240 X(Error_RandR_Output_Info_Not_Found , 15 , "XCB RandR Output Information was not found" ) \
241 X(Error_RandR_Screen_Resources_Not_Found , 16 , "XCB RandR could not locate any screen resources" ) \
242 X(Error_RandR_Version_Too_Old , 17 , "XCB RandR version is too old" ) \
243 X(Error_Xcb_Fullscreen_Not_Available , 18 , "The XCB Window Manager does not support fullscreen windows." ) \
244 X(Error_Xcb_Hidden_Not_Available , 19 , "The XCB Window Manager does not support hiding windows." ) \
245 X(Error_Xcb_Maximized_Window_Not_Available , 20 , "The XCB Window Manager does not support maximized windows." ) \
246 X(Error_Xcb_NETWM_State_Not_Available , 21 , "The XCB NETWM protocol extention is not supported." ) \
247 X(Error_Xcb_WM_Delete_Window_Not_Available , 22 , "The XCB Window Manager does not support the delete protocol." ) \
248 X(Error_Xcb_WM_Protocols_Not_Available , 23 , "The XCB Window Manager protocols are not available." ) \
249 X(Error_Xcb_Xkb_Not_Available , 24 , "The XCB XKB Extiension v1.0 is not available." ) \
260 #define X(name_, val_, mesg_) \
261 static constexpr int name_ = val_;
262 ZAKERO_XENIUM__ERROR_DATA
265 static constexpr int32_t Window_Size_Minimum = 100;
400 [[nodiscard]] static
Xenium*
connect(const std::
string&) noexcept;
401 [[nodiscard]] static
Xenium*
connect(std::error_code&) noexcept;
402 [[nodiscard]] static
Xenium*
connect(const std::
string&, std::error_code&) noexcept;
418 std::string name =
"";
423 uint32_t physical_width_mm = 0;
424 uint32_t physical_height_mm = 0;
425 int32_t subpixel = 0;
426 int32_t transform = 0;
427 float pixels_per_mm_horizontal = 0.0;
428 float pixels_per_mm_vertical = 0.0;
437 using OutputId = uint32_t;
439 using LambdaOutputId = std::function<void(
const Xenium::OutputId)>;
441 using VectorOutputId = std::vector<Xenium::OutputId>;
446 [[nodiscard]] Xenium::VectorOutputId
outputVector() const noexcept;
508 void classSet(
const std::string&) noexcept;
509 void titleSet(
const std::string&) noexcept;
557 [[nodiscard]] std::error_code
minimize() noexcept;
594 [[nodiscard]] uint32_t
time()
const noexcept;
601 uint8_t* frame_buffer;
605 size_t frame_buffer_length;
628 void disconnect() noexcept;
633 [[nodiscard]] std::error_code init(xcb_connection_t*,
int) noexcept;
641 std::jthread event_loop;
642 std::atomic<
bool> event_loop_is_running;
646 void eventLoopStart() noexcept;
647 static
void eventLoop(std::stop_token,
Xenium*) noexcept;
656 Xenium::LambdaOutputId output_on_add = {};
657 Xenium::LambdaOutputId output_on_change = {};
658 Xenium::LambdaOutputId output_on_remove = {};
659 Xenium::Map_OutputId_Output output_map = {};
660 mutable std::mutex output_mutex = {};
664 [[nodiscard]]
const Xenium::Output&
output(
const int16_t,
const int16_t, Xenium::OutputId&) noexcept;
665 [[nodiscard]] std::error_code outputInit() noexcept;
666 [[nodiscard]] std::error_code outputAdd(xcb_randr_crtc_t, xcb_randr_output_t) noexcept;
667 void outputAdd(const xcb_randr_get_crtc_info_reply_t*, const xcb_randr_get_output_info_reply_t*) noexcept;
672 std::mutex xenium_window_mutex = {};
676 [[nodiscard]] std::pair<float, float> convertPixelToMm(
const Xenium::Output&, int32_t, int32_t)
const noexcept;
677 [[nodiscard]] std::pair<float, float> convertPixelToPercent(
const Xenium::Output&, int32_t, int32_t)
const noexcept;
678 [[nodiscard]] std::pair<int32_t, int32_t> convertMmToPixel(
const Xenium::Output&,
float,
float)
const noexcept;
679 [[nodiscard]] std::pair<int32_t, int32_t> convertPercentToPixel(
const Xenium::Output&,
float,
float)
const noexcept;
694 uint32_t decorations;
699 struct WindowCreateData
701 std::promise<void> barrier;
702 std::error_code error;
704 Xenium::OutputId output_id;
705 xcb_atom_t atom_close_request;
707 Xenium::SizeUnit size_unit;
708 Xenium::SizeMm size_mm;
709 Xenium::SizePercent size_percent;
710 Xenium::SizePixel size_pixel;
712 xcb_create_window_value_list_t& value_list;
715 struct WindowDestroyData
717 std::promise<void> barrier;
722 struct WindowDeleteData
725 xcb_atom_t atom_close_request = XCB_ATOM_NONE;
728 struct WindowSizeData
730 Xenium::SizeMm mm = { };
731 Xenium::SizeMm mm_minimum = { };
732 Xenium::SizeMm mm_maximum = { };
734 Xenium::SizePercent percent = { };
735 Xenium::SizePercent percent_minimum = { };
736 Xenium::SizePercent percent_maximum = { };
738 Xenium::SizePixel pixel = { };
739 Xenium::SizePixel pixel_minimum = { };
740 Xenium::SizePixel pixel_maximum = { };
742 Xenium::SizeUnit unit = { };
745 struct WindowModeData
751 struct WindowDecorationsData
757 struct WindowOnButtonData
764 struct WindowOnEnterData
771 struct WindowOnMotionData
778 struct WindowKeyboardData
784 using WindowDecorationsMap = std::unordered_map<Xenium::WindowId, Xenium::WindowDecorationsData>;
785 using WindowDeleteMap = std::unordered_map<Xenium::WindowId, Xenium::WindowDeleteData>;
786 using WindowFocusMap = std::unordered_map<Xenium::WindowId, Xenium::LambdaBool>;
787 using WindowKeyboard = std::unordered_map<Xenium::WindowId, Xenium::WindowKeyboardData>;
788 using WindowMap = std::unordered_map<Xenium::WindowId, Xenium::Window*>;
789 using WindowModeMap = std::unordered_map<Xenium::WindowId, Xenium::WindowModeData>;
790 using WindowOnAxisMap = std::unordered_map<Xenium::WindowId, Xenium::LambdaAxis>;
791 using WindowOnButtonMap = std::unordered_map<Xenium::WindowId, Xenium::WindowOnButtonData>;
792 using WindowOnEnterMap = std::unordered_map<Xenium::WindowId, Xenium::WindowOnEnterData>;
793 using WindowOnKeyMap = std::unordered_map<Xenium::WindowId, Xenium::LambdaKey>;
794 using WindowOnLeaveMap = std::unordered_map<Xenium::WindowId, Xenium::Lambda>;
795 using WindowOnMotionMap = std::unordered_map<Xenium::WindowId, Xenium::WindowOnMotionData>;
796 using WindowOutputMap = std::unordered_map<Xenium::WindowId, Xenium::OutputId>;
797 using WindowReadyMap = std::unordered_map<Xenium::WindowId, bool>;
798 using WindowSizeMap = std::unordered_map<Xenium::WindowId, Xenium::WindowSizeData>;
799 using WindowToCreate = std::vector<Xenium::WindowCreateData*>;
800 using WindowToDestroy = std::vector<Xenium::WindowDestroyData*>;
804 Xenium::WindowDecorationsMap window_decorations_map = {};
805 Xenium::WindowDeleteMap window_delete_map = {};
806 Xenium::WindowFocusMap window_focus_map = {};
807 Xenium::WindowKeyboard window_keyboard = {};
808 Xenium::WindowMap window_map = {};
809 Xenium::WindowModeMap window_mode_map = {};
810 Xenium::WindowOnAxisMap window_on_axis_map = {};
811 Xenium::WindowOnButtonMap window_on_button_map = {};
812 Xenium::WindowOnEnterMap window_on_enter_map = {};
813 Xenium::WindowOnKeyMap window_on_key_map = {};
814 Xenium::WindowOnLeaveMap window_on_leave_map = {};
815 Xenium::WindowOnMotionMap window_on_motion_map = {};
816 Xenium::WindowOutputMap window_output_map = {};
817 Xenium::WindowReadyMap window_ready_map = {};
818 Xenium::WindowSizeMap window_size_map = {};
819 Xenium::WindowToCreate window_to_create = {};
820 Xenium::WindowToDestroy window_to_destroy = {};
824 [[nodiscard]] std::error_code windowBorder(
const Xenium::WindowId,
const bool) noexcept;
825 void windowCreateAddToQueue(Xenium::WindowCreateData*) noexcept;
826 void windowDestroyAddToQueue(Xenium::WindowDestroyData*) noexcept;
827 [[nodiscard]] std::error_code windowLocationSet(
const Xenium::WindowId,
const Xenium::PointPixel&) noexcept;
828 [[nodiscard]] std::error_code windowMinimize(
const Xenium::WindowId) noexcept;
830 bool windowPropertySet(
Xenium::WindowId,
const xcb_atom_t,
const xcb_atom_t, xcb_generic_error_t&) noexcept;
831 bool windowPropertySet(
Xenium::WindowId,
const xcb_atom_t,
const std::string&, xcb_generic_error_t&) noexcept;
834 void windowResizeTo(
const Xenium::Output&, Xenium::WindowSizeData&,
const xcb_configure_notify_event_t*) noexcept;
835 std::error_code windowSizeSet(
const Xenium::WindowId,
const Xenium::SizePixel&) noexcept;
836 [[nodiscard]] std::error_code windowSizeSetMinMax(
const Xenium::WindowId,
const int32_t,
const int32_t,
const int32_t,
const int32_t) noexcept;
837 std::error_code windowSizeSetMinMax(
const Xenium::Output&,
const Xenium::WindowId, Xenium::WindowSizeData&) noexcept;
842 xcb_connection_t* connection =
nullptr;
843 const xcb_setup_t* setup =
nullptr;
844 xcb_screen_t* screen =
nullptr;
848 void xcbEvent(
const xcb_button_press_event_t*) noexcept;
849 void xcbEvent(
const xcb_client_message_event_t*) noexcept;
850 void xcbEvent(
const xcb_configure_notify_event_t*) noexcept;
851 void xcbEvent(
const xcb_enter_notify_event_t*) noexcept;
852 void xcbEvent(
const xcb_expose_event_t*) noexcept;
853 void xcbEvent(
const xcb_focus_in_event_t*) noexcept;
854 void xcbEvent(
const xcb_gravity_notify_event_t*) noexcept;
855 void xcbEvent(
const xcb_key_press_event_t*) noexcept;
856 void xcbEvent(
const xcb_map_notify_event_t*) noexcept;
857 void xcbEvent(
const xcb_motion_notify_event_t*) noexcept;
858 void xcbEvent(
const xcb_property_notify_event_t*) noexcept;
859 void xcbEvent(
const xcb_reparent_notify_event_t*) noexcept;
860 void xcbEvent(
const xcb_unmap_notify_event_t*) noexcept;
862 void xcbWindowCreate(Xenium::WindowCreateData*) noexcept;
863 [[nodiscard]] std::error_code xcbWindowCreateValidate(Xenium::WindowCreateData*) noexcept;
864 [[nodiscard]] std::error_code xcbWindowCreateClient(Xenium::WindowCreateData*) noexcept;
865 [[nodiscard]] std::error_code xcbWindowCreateInit(Xenium::WindowCreateData*) noexcept;
866 void xcbWindowDestroy(Xenium::WindowDestroyData*) noexcept;
871 xcb_atom_t atom_motif_wm_hints = XCB_ATOM_NONE;
872 xcb_atom_t atom_net_frame_extents = XCB_ATOM_NONE;
873 xcb_atom_t atom_net_wm_state = XCB_ATOM_NONE;
874 xcb_atom_t atom_net_wm_state_fullscreen = XCB_ATOM_NONE;
875 xcb_atom_t atom_net_wm_state_hidden = XCB_ATOM_NONE;
876 xcb_atom_t atom_net_wm_state_maximized_horz = XCB_ATOM_NONE;
877 xcb_atom_t atom_net_wm_state_maximized_vert = XCB_ATOM_NONE;
878 xcb_atom_t atom_wm_change_state = XCB_ATOM_NONE;
879 xcb_atom_t atom_wm_delete_window = XCB_ATOM_NONE;
880 xcb_atom_t atom_wm_protocols = XCB_ATOM_NONE;
884 [[nodiscard]] std::error_code atomInit() noexcept;
885 [[nodiscard]] xcb_atom_t atomCreateDeleteWindow(const
WindowId, xcb_generic_error_t&) noexcept;
886 [[nodiscard]] std::
string atomName(const xcb_atom_t) noexcept;
887 [[nodiscard]] std::vector<xcb_atom_t> atomValueAtom(const Xenium::
WindowId, const xcb_atom_t, xcb_generic_error_t&) noexcept;
888 [[nodiscard]] std::vector<int32_t> atomValueData(const Xenium::
WindowId, const xcb_atom_t, const xcb_atom_t, const
size_t, xcb_generic_error_t&) noexcept;
889 [[nodiscard]] xcb_atom_t internAtom(const std::
string&, const
bool, xcb_generic_error_t&) noexcept;
890 [[nodiscard]] xcb_intern_atom_cookie_t internAtomRequest(const std::
string&, const
bool = true) noexcept;
891 [[nodiscard]] xcb_atom_t internAtomReply(const xcb_intern_atom_cookie_t, xcb_generic_error_t&) noexcept;
896 int randr_error_base = 0;
897 int randr_event_base = 0;
898 int randr_query_version_major = 0;
899 int randr_query_version_minor = 0;
903 [[nodiscard]] std::error_code randrInit() noexcept;
904 void randrEvent(const xcb_randr_crtc_change_t*) noexcept;
905 void randrEvent(const xcb_randr_output_change_t*) noexcept;
906 void randrEvent(const xcb_randr_notify_event_t*) noexcept;
907 void randrEvent(const xcb_randr_screen_change_notify_event_t*) noexcept;
914 uint32_t repeat_delay_ms = 600;
915 uint32_t repeat_interval_ms = 50;
920 Xenium::Key key = { 0, 0, Xenium::KeyState::Released };
921 Xenium::KeyModifier modifier = { 0 };
923 uint32_t repeat_time = { 0 };
926 using KeyDataArray = std::array<Xenium::KeyData, 256>;
930 Xenium::KeyDataArray key_data_array = { };
931 Xenium::KeyModifier key_modifier = { 0 };
932 Xenium::XkbControls xkb_controls = { };
933 uint16_t xkb_modifier_pressed = 0;
937 [[nodiscard]] std::error_code xkbInit() noexcept;
938 inline
void keyDataArrayClear() noexcept;
939 inline
void keyDataArrayProcess() noexcept;
940 void xkbControlsUpdate() noexcept;
941 void xkbIndicatorStateUpdate() noexcept;
946 [[nodiscard]]
bool requestCheckHasError(const xcb_void_cookie_t&, xcb_generic_error_t&) noexcept;
950 Xenium(const Xenium&) = delete;
951 Xenium& operator=(const Xenium&) = delete;
957 [[nodiscard]] std::
string to_string(const std::vector<xcb_atom_t>&) noexcept;
958 [[nodiscard]] std::
string to_string(const std::vector<int32_t>&) noexcept;
959 [[nodiscard]] std::
string to_string(const xcb_generic_error_t&) noexcept;
960 [[nodiscard]] std::
string to_string(const xcb_button_press_event_t&) noexcept;
961 [[nodiscard]] std::
string to_string(const xcb_client_message_event_t&) noexcept;
962 [[nodiscard]] std::
string to_string(const xcb_configure_notify_event_t&) noexcept;
963 [[nodiscard]] std::
string to_string(const xcb_enter_notify_event_t&) noexcept;
964 [[nodiscard]] std::
string to_string(const xcb_expose_event_t&) noexcept;
965 [[nodiscard]] std::
string to_string(const xcb_focus_in_event_t&) noexcept;
966 [[nodiscard]] std::
string to_string(const xcb_generic_event_t&) noexcept;
967 [[nodiscard]] std::
string to_string(const xcb_gravity_notify_event_t&) noexcept;
968 [[nodiscard]] std::
string to_string(const xcb_key_press_event_t&) noexcept;
969 [[nodiscard]] std::
string to_string(const xcb_map_notify_event_t&) noexcept;
970 [[nodiscard]] std::
string to_string(const xcb_motion_notify_event_t&) noexcept;
971 [[nodiscard]] std::
string to_string(const xcb_property_notify_event_t&) noexcept;
972 [[nodiscard]] std::
string to_string(const xcb_reparent_notify_event_t&) noexcept;
973 [[nodiscard]] std::
string to_string(const xcb_unmap_notify_event_t&) noexcept;
974 [[nodiscard]] std::
string to_string(const xcb_format_t&) noexcept;
975 [[nodiscard]] std::
string to_string(const xcb_screen_t&) noexcept;
976 [[nodiscard]] std::
string to_string(const xcb_setup_t&) noexcept;
977 [[nodiscard]] std::
string to_string(const xcb_randr_screen_change_notify_event_t&) noexcept;
978 [[nodiscard]] std::
string to_string(const Xenium::Key&) noexcept;
979 [[nodiscard]] std::
string to_string(const Xenium::KeyModifier&) noexcept;
980 [[nodiscard]] std::
string to_string(const Xenium::
KeyState) noexcept;
981 [[nodiscard]] std::
string to_string(const Xenium::Output&) noexcept;
982 [[nodiscard]] std::
string to_string(const Xenium::PointMm) noexcept;
983 [[nodiscard]] std::
string to_string(const Xenium::PointPercent) noexcept;
984 [[nodiscard]] std::
string to_string(const Xenium::PointPixel) noexcept;
985 [[nodiscard]] std::
string to_string(const Xenium::PointerAxis&) noexcept;
987 [[nodiscard]] std::
string to_string(const Xenium::
PointerAxisType) noexcept;
988 [[nodiscard]] std::
string to_string(const Xenium::PointerButton&) noexcept;
990 [[nodiscard]] std::
string to_string(const Xenium::SizeMm&) noexcept;
991 [[nodiscard]] std::
string to_string(const Xenium::SizePercent&) noexcept;
992 [[nodiscard]] std::
string to_string(const Xenium::SizePixel&) noexcept;
994 [[nodiscard]] std::
string to_string(const Xenium::
WindowMode) noexcept;
1002 #ifdef ZAKERO_XENIUM_IMPLEMENTATION
1012 #ifdef ZAKERO__DOXYGEN_DEFINE_DOCS
1035 #define ZAKERO_XENIUM_IMPLEMENTATION
1045 #define ZAKERO_XENIUM_ENABLE_DEBUG
1055 #define ZAKERO_XENIUM_ENABLE_SAFE_MODE
1062 #ifndef _NET_WM_STATE_REMOVE
1066 #define _NET_WM_STATE_REMOVE 0
1069 #ifndef _NET_WM_STATE_ADD
1073 #define _NET_WM_STATE_ADD 1
1076 #ifndef _NET_WM_STATE_TOGGLE
1080 #define _NET_WM_STATE_TOGGLE 2
1098 #ifdef ZAKERO_XENIUM_ENABLE_DEBUG
1099 #define ZAKERO_XENIUM__DEBUG_ENABLED true
1101 #define ZAKERO_XENIUM__DEBUG_ENABLED false
1119 #ifdef ZAKERO_XENIUM_ENABLE_DEBUG
1120 #define ZAKERO_XENIUM__DEBUG_DISABLED false
1122 #define ZAKERO_XENIUM__DEBUG_DISABLED true
1138 #ifndef ZAKERO_XENIUM_DEBUG_STREAM
1139 #define ZAKERO_XENIUM_DEBUG_STREAM std::cerr
1160 #define ZAKERO_XENIUM__DEBUG \
1161 if(ZAKERO_XENIUM__DEBUG_DISABLED) {} \
1162 else ZAKERO_XENIUM_DEBUG_STREAM \
1163 << "pid(" << std::to_string(int64_t(ZAKERO_PID)) \
1164 << ") " __FILE__ "(" \
1165 << std::to_string(__LINE__) \
1167 << __PRETTY_FUNCTION__ \
1186 #define ZAKERO_XENIUM__DEBUG_VAR(var_) \
1187 ZAKERO_XENIUM__DEBUG \
1188 << #var_ << ": " << var_ \
1206 #define ZAKERO_XENIUM__DEBUG_BOOL(var_) \
1207 ZAKERO_XENIUM__DEBUG \
1208 << #var_ << ": " << std::boolalpha << var_ \
1226 #define ZAKERO_XENIUM__DEBUG_ERROR(var_) \
1227 ZAKERO_XENIUM__DEBUG \
1228 << "Error: " << var_ \
1239 #define ZAKERO_XENIUM__OUTPUT_SUBPIXEL \
1240 X(XCB_RENDER_SUB_PIXEL_UNKNOWN , "Unkown Geometry" ) \
1241 X(XCB_RENDER_SUB_PIXEL_HORIZONTAL_RGB , "Horizontal RGB" ) \
1242 X(XCB_RENDER_SUB_PIXEL_HORIZONTAL_BGR , "Horizontal BGR" ) \
1243 X(XCB_RENDER_SUB_PIXEL_VERTICAL_RGB , "Vertical RGB" ) \
1244 X(XCB_RENDER_SUB_PIXEL_VERTICAL_BGR , "Vertical BGR" ) \
1245 X(XCB_RENDER_SUB_PIXEL_NONE , "No Geometry" ) \
1252 #define ZAKERO_XENIUM__OUTPUT_TRANSFORM \
1253 X(XCB_RANDR_TRANSFORM_UNIT , "Unit" ) \
1254 X(XCB_RANDR_TRANSFORM_SCALE_UP , "Scale Up" ) \
1255 X(XCB_RANDR_TRANSFORM_SCALE_DOWN , "Scale Down" ) \
1256 X(XCB_RANDR_TRANSFORM_PROJECTIVE , "Projective" ) \
1270 #define ZAKERO_XENIUM__ERROR(err_) std::error_code(err_, XeniumErrorCategory)
1426 constexpr uint32_t Size_Max = (uint32_t)std::numeric_limits<int32_t>::max();
1433 constexpr uint32_t XCB_XKB_INDICATOR_STATE_CAPSLOCK = 0x00000001;
1438 constexpr uint32_t XCB_XKB_INDICATOR_STATE_NUMLOCK = 0x00000002;
1443 constexpr std::array<uint32_t, 8> Pointer_Button_Event_Code =
1457 const uint32_t Default_Value_Mask = 0
1462 | XCB_CW_BIT_GRAVITY
1463 | XCB_CW_WIN_GRAVITY
1464 | XCB_CW_BACKING_STORE
1478 xcb_create_window_value_list_t Default_Value_List =
1479 { .background_pixmap = XCB_BACK_PIXMAP_NONE
1480 , .background_pixel = 0
1481 , .border_pixmap = XCB_BACK_PIXMAP_NONE
1483 , .bit_gravity = XCB_GRAVITY_CENTER
1484 , .win_gravity = XCB_GRAVITY_NORTH_EAST
1485 , .backing_store = XCB_BACKING_STORE_NOT_USEFUL
1486 , .backing_planes = 0
1487 , .backing_pixel = 0
1488 , .override_redirect = 0
1491 | XCB_EVENT_MASK_KEY_PRESS
1492 | XCB_EVENT_MASK_KEY_RELEASE
1493 | XCB_EVENT_MASK_BUTTON_PRESS
1494 | XCB_EVENT_MASK_BUTTON_RELEASE
1495 | XCB_EVENT_MASK_ENTER_WINDOW
1496 | XCB_EVENT_MASK_LEAVE_WINDOW
1497 | XCB_EVENT_MASK_POINTER_MOTION
1506 | XCB_EVENT_MASK_EXPOSURE
1508 | XCB_EVENT_MASK_STRUCTURE_NOTIFY
1512 | XCB_EVENT_MASK_FOCUS_CHANGE
1513 | XCB_EVENT_MASK_PROPERTY_CHANGE
1516 , .do_not_propogate_mask = XCB_EVENT_MASK_NO_EVENT
1517 , .colormap = XCB_COPY_FROM_PARENT
1531 class XeniumErrorCategory_
1532 :
public std::error_category
1541 constexpr XeniumErrorCategory_() noexcept
1550 const char* name()
const noexcept
override
1552 return "zakero.Xenium";
1561 std::string message(
int condition
1562 )
const noexcept
override
1566 #define X(name_, val_, mesg_) \
1567 case val_: return mesg_;
1568 ZAKERO_XENIUM__ERROR_DATA
1572 return "Unknown error condition";
1574 } XeniumErrorCategory;
1582 Xenium::LambdaKey LambdaKey_DoNothing = [](
const Xenium::Key&,
const Xenium::KeyModifier&) noexcept {};
1583 Xenium::LambdaAxis LambdaAxis_DoNothing = [](
const Xenium::PointerAxis&,
const Xenium::KeyModifier&) noexcept {};
1584 Xenium::LambdaButtonMm LambdaButtonMm_DoNothing = [](
const Xenium::PointerButton&,
const Xenium::PointMm&,
const Xenium::KeyModifier&) noexcept {};
1585 Xenium::LambdaButtonPercent LambdaButtonPercent_DoNothing = [](
const Xenium::PointerButton&,
const Xenium::PointPercent&,
const Xenium::KeyModifier&) noexcept {};
1586 Xenium::LambdaButtonPixel LambdaButtonPixel_DoNothing = [](
const Xenium::PointerButton&,
const Xenium::PointPixel&,
const Xenium::KeyModifier&) noexcept {};
1587 Xenium::LambdaPointMm LambdaPointMm_DoNothing = [](
const Xenium::PointMm&,
const Xenium::KeyModifier&) noexcept {};
1588 Xenium::LambdaPointPercent LambdaPointPercent_DoNothing = [](
const Xenium::PointPercent&,
const Xenium::KeyModifier&) noexcept {};
1589 Xenium::LambdaPointPixel LambdaPointPixel_DoNothing = [](
const Xenium::PointPixel&,
const Xenium::KeyModifier&) noexcept {};
1591 Xenium::LambdaOutputId LambdaOutputId_DoNothing = [](
const Xenium::OutputId) noexcept {};
1610 std::error_code convertConnectionError(
int xcb_error_code
1613 switch(xcb_error_code)
1616 return ZAKERO_XENIUM__ERROR(Xenium::Error_None);
1618 case XCB_CONN_ERROR:
1619 return ZAKERO_XENIUM__ERROR(Xenium::Error_Connection_Failed);
1621 case XCB_CONN_CLOSED_EXT_NOTSUPPORTED:
1622 return ZAKERO_XENIUM__ERROR(Xenium::Error_Extension_Not_Supported);
1624 case XCB_CONN_CLOSED_MEM_INSUFFICIENT:
1625 return ZAKERO_XENIUM__ERROR(Xenium::Error_Not_Enough_Memory);
1627 case XCB_CONN_CLOSED_REQ_LEN_EXCEED:
1628 return ZAKERO_XENIUM__ERROR(Xenium::Error_Request_Too_Long);
1630 case XCB_CONN_CLOSED_PARSE_ERR:
1631 return ZAKERO_XENIUM__ERROR(Xenium::Error_Invalid_Display_Name);
1633 case XCB_CONN_CLOSED_INVALID_SCREEN:
1634 return ZAKERO_XENIUM__ERROR(Xenium::Error_Invalid_Screen);
1637 return ZAKERO_XENIUM__ERROR(Xenium::Error_Unknown);
1656 std::error_code validateMinMax(
const Type& min
1666 return ZAKERO_XENIUM__ERROR(Xenium::Error_Window_Size_Too_Small);
1670 && (min.width > max.width)
1673 return ZAKERO_XENIUM__ERROR(Xenium::Error_Minimum_Size_Greater_Than_Maximum_Size);
1677 && (min.height > max.height)
1680 return ZAKERO_XENIUM__ERROR(Xenium::Error_Minimum_Size_Greater_Than_Maximum_Size);
1683 return ZAKERO_XENIUM__ERROR(Xenium::Error_None);
2341 Xenium::Xenium() noexcept
2343 , event_loop_is_running(
false)
2359 if(event_loop_is_running || event_loop.joinable())
2361 event_loop.request_stop();
2392 std::error_code error;
2421 std::error_code error;
2484 , std::error_code& error
2487 const char* display_name =
nullptr;
2489 if(display.empty() ==
false)
2491 display_name = display.c_str();
2495 int screen_number = 0;
2496 xcb_connection_t* connection = xcb_connect(display_name, &screen_number);
2497 int xcb_error = xcb_connection_has_error(connection);
2500 error = convertConnectionError(xcb_error);
2502 ZAKERO_XENIUM__DEBUG_ERROR(error);
2510 error = xenium->init(connection, screen_number);
2515 ZAKERO_XENIUM__DEBUG_ERROR(error);
2520 xenium->eventLoopStart();
2522 error = xenium->atomInit();
2527 ZAKERO_XENIUM__DEBUG_ERROR(error);
2532 error = ZAKERO_XENIUM__ERROR(Error_None);
2545 void Xenium::disconnect() noexcept
2547 this->setup =
nullptr;
2551 xcb_disconnect(this->connection);
2552 connection =
nullptr;
2566 std::error_code Xenium::init(xcb_connection_t* connection
2570 this->connection = connection;
2573 this->setup = xcb_get_setup(this->connection);
2574 ZAKERO_XENIUM__DEBUG_VAR(
to_string(*setup));
2577 xcb_screen_iterator_t screen_iterator = xcb_setup_roots_iterator(this->setup);
2579 for(
int i = 0; i < screen_number; i++)
2581 xcb_screen_next(&screen_iterator);
2584 this->screen = screen_iterator.data;
2585 ZAKERO_XENIUM__DEBUG_VAR(
to_string(*screen));
2588 std::error_code error;
2593 ZAKERO_XENIUM__DEBUG_ERROR(error);
2599 error = randrInit();
2602 ZAKERO_XENIUM__DEBUG_ERROR(error);
2607 error = outputInit();
2610 ZAKERO_XENIUM__DEBUG_ERROR(error);
2615 return ZAKERO_XENIUM__ERROR(Error_None);
2632 void Xenium::eventLoopStart() noexcept
2634 event_loop = std::jthread(&Xenium::eventLoop,
this);
2636 while(event_loop_is_running.load() ==
false)
2639 std::this_thread::sleep_for(std::chrono::nanoseconds(42));
2663 void Xenium::eventLoop(std::stop_token thread_token
2667 const int Randr_Notify_Event = xenium->randr_event_base + XCB_RANDR_NOTIFY;
2669 xcb_generic_event_t*
event =
nullptr;
2671 xenium->event_loop_is_running.store(
true);
2674 while(thread_token.stop_requested() ==
false)
2679 event = xcb_poll_for_event(xenium->connection);
2681 if(event ==
nullptr)
2687 xenium->keyDataArrayProcess();
2692 switch(event->response_type & 0x7f)
2694 case XCB_CLIENT_MESSAGE:
2696 (xcb_client_message_event_t*)event
2702 case XCB_BUTTON_PRESS:
2704 case XCB_BUTTON_RELEASE:
2706 (xcb_button_press_event_t*)event
2712 case XCB_ENTER_NOTIFY: [[fallthrough]];
2713 case XCB_LEAVE_NOTIFY:
2715 (xcb_enter_notify_event_t*)event
2722 (xcb_expose_event_t*)event
2727 case XCB_FOCUS_IN: [[fallthrough]];
2730 (xcb_focus_in_event_t*)event
2736 case XCB_KEY_PRESS: [[fallthrough]];
2737 case XCB_KEY_RELEASE:
2739 (xcb_key_press_event_t*)event
2744 case XCB_MOTION_NOTIFY:
2746 (xcb_motion_notify_event_t*)event
2751 case XCB_PROPERTY_NOTIFY:
2753 (xcb_property_notify_event_t*)event
2758 case XCB_CONFIGURE_NOTIFY:
2760 (xcb_configure_notify_event_t*)event
2764 case XCB_GRAVITY_NOTIFY:
2766 (xcb_gravity_notify_event_t*)event
2770 case XCB_MAP_NOTIFY:
2772 (xcb_map_notify_event_t*)event
2776 case XCB_REPARENT_NOTIFY:
2778 (xcb_reparent_notify_event_t*)event
2782 case XCB_UNMAP_NOTIFY:
2784 (xcb_unmap_notify_event_t*)event
2790 if(event->response_type == Randr_Notify_Event)
2792 ZAKERO_XENIUM__DEBUG <<
"RandR Event: " <<
to_string(*event) <<
'\n';
2794 (xcb_randr_notify_event_t*)event
2799 ZAKERO_XENIUM__DEBUG <<
"Unknown Event: " <<
to_string(*event) <<
'\n';
2828 xenium->xenium_window_mutex.lock();
2830 for(Xenium::WindowCreateData* window_data : xenium->window_to_create)
2832 xenium->xcbWindowCreate(window_data);
2833 window_data->barrier.set_value();
2836 xenium->window_to_create.clear();
2838 for(Xenium::WindowDestroyData* window_data : xenium->window_to_destroy)
2840 xenium->xcbWindowDestroy(window_data);
2841 window_data->barrier.set_value();
2844 xenium->window_to_destroy.clear();
2846 xenium->xenium_window_mutex.unlock();
2848 std::this_thread::yield();
2851 xenium->event_loop_is_running.store(
false);
2867 return xkb_controls.repeat_delay_ms;
2880 return 1000 / xkb_controls.repeat_interval_ms;
2901 std::lock_guard<std::mutex> lock(output_mutex);
2903 if(output_map.contains(output_id) ==
false)
2905 ZAKERO_XENIUM__DEBUG
2906 <<
"Invalid output_id: "
2907 << std::to_string(output_id)
2913 return output_map.at(output_id);
2928 Xenium::VectorOutputId vector(output_map.size());
2931 std::lock_guard<std::mutex> lock(output_mutex);
2933 for(
const auto& iter : output_map)
2935 vector.push_back(iter.first);
2954 switch(subpixel_format)
2956 #define X(value_, name_) \
2957 case value_: return name_;
2958 ZAKERO_XENIUM__OUTPUT_SUBPIXEL
2979 #define X(value_, name_) \
2980 case value_: return name_;
2981 ZAKERO_XENIUM__OUTPUT_TRANSFORM
3000 std::lock_guard<std::mutex> lock(output_mutex);
3002 if(output_map.contains(output_id) ==
false)
3004 return { point.time, 0, 0 };
3009 auto p = convertPixelToMm(
output, point.
x, point.y);
3011 return { point.time, p.first, p.second };
3027 std::lock_guard<std::mutex> lock(output_mutex);
3029 if(output_map.contains(output_id) ==
false)
3031 return { point.time, 0, 0 };
3036 auto p = convertPixelToPercent(
output, point.
x, point.y);
3038 return { point.time, p.first, p.second };
3054 std::lock_guard<std::mutex> lock(output_mutex);
3056 if(output_map.contains(output_id) ==
false)
3058 return { point.time, 0, 0 };
3063 auto p = convertMmToPixel(
output, point.
x, point.y);
3065 return { point.time, p.first, p.second };
3081 std::lock_guard<std::mutex> lock(output_mutex);
3083 if(output_map.contains(output_id) ==
false)
3085 return { point.time, 0, 0 };
3090 auto p = convertPercentToPixel(
output, point.
x, point.y);
3092 return { point.time, p.first, p.second };
3108 std::lock_guard<std::mutex> lock(output_mutex);
3110 if(output_map.contains(output_id) ==
false)
3117 auto p = convertPixelToMm(
output, size.
width, size.height);
3119 return { p.first, p.second };
3135 std::lock_guard<std::mutex> lock(output_mutex);
3137 if(output_map.contains(output_id) ==
false)
3144 auto p = convertPixelToPercent(
output, size.
width, size.height);
3146 return { p.first, p.second };
3161 std::lock_guard<std::mutex> lock(output_mutex);
3163 if(output_map.contains(output_id) ==
false)
3170 auto p = convertMmToPixel(
output, size.
width, size.height);
3172 return { p.first, p.second };
3187 std::lock_guard<std::mutex> lock(output_mutex);
3189 if(output_map.contains(output_id) ==
false)
3196 auto p = convertPercentToPixel(
output, size.
width, size.height);
3198 return { p.first, p.second };
3212 if(lambda ==
nullptr)
3214 output_on_add = LambdaOutputId_DoNothing;
3218 output_on_add = lambda;
3233 if(lambda ==
nullptr)
3235 output_on_change = LambdaOutputId_DoNothing;
3239 output_on_change = lambda;
3254 if(lambda ==
nullptr)
3256 output_on_remove = LambdaOutputId_DoNothing;
3260 output_on_remove = lambda;
3289 , OutputId& output_id
3292 for(
const auto& iter : output_map)
3294 const Output&
output = iter.second;
3302 output_id = iter.first;
3308 uint64_t distance = std::numeric_limits<uint64_t>::max();
3310 for(
const auto& iter : output_map)
3312 const Output&
output = iter.second;
3317 uint64_t dist = std::abs(x - output_x) + std::abs(y - output_y);
3321 output_id = iter.first;
3325 return output_map[output_id];
3337 std::error_code Xenium::outputInit() noexcept
3339 xcb_generic_error_t* xcb_generic_error =
nullptr;
3341 xcb_randr_get_screen_resources_current_reply_t* screen_resources =
3342 xcb_randr_get_screen_resources_current_reply(this->connection
3343 , xcb_randr_get_screen_resources_current(this->connection
3344 , this->screen->root
3346 , &xcb_generic_error
3349 if(screen_resources ==
nullptr)
3351 ZAKERO_XENIUM__DEBUG_ERROR(
3352 ZAKERO_XENIUM__ERROR(Error_RandR_Screen_Resources_Not_Found)
3355 return ZAKERO_XENIUM__ERROR(Error_RandR_Screen_Resources_Not_Found);
3358 xcb_randr_output_t* output_list =
3359 xcb_randr_get_screen_resources_current_outputs(screen_resources
3362 int output_list_size =
3363 xcb_randr_get_screen_resources_current_outputs_length(screen_resources
3366 # if ZAKERO_XENIUM__DEBUG_ENABLED
3367 if(output_list_size == 0)
3369 ZAKERO_XENIUM__DEBUG
3370 <<
"No outputs where found in the Screen Resources"
3375 for(
int i = 0; i < output_list_size; i++)
3377 xcb_randr_get_output_info_reply_t* output_info =
3378 xcb_randr_get_output_info_reply(this->connection
3379 , xcb_randr_get_output_info(this->connection
3381 , screen_resources->config_timestamp
3383 , &xcb_generic_error
3386 if(output_info ==
nullptr
3387 || output_info->connection != XCB_RANDR_CONNECTION_CONNECTED
3388 || output_info->crtc == XCB_NONE
3396 xcb_randr_get_crtc_info_reply_t* crtc_info =
3397 xcb_randr_get_crtc_info_reply(this->connection
3398 , xcb_randr_get_crtc_info(this->connection
3400 , screen_resources->config_timestamp
3402 , &xcb_generic_error
3405 if(crtc_info ==
nullptr)
3414 if(output_info->mm_width == 0 || output_info->mm_height == 0)
3416 ZAKERO_XENIUM__DEBUG_ERROR(
3417 ZAKERO_XENIUM__ERROR(Error_RandR_Output_Info_Is_Incomplete)
3420 const float pixels_per_mm_horizontal = (float)this->screen->width_in_pixels / this->screen->width_in_millimeters;
3421 const float pixels_per_mm_vertical = (
float)this->screen->height_in_pixels / this->screen->height_in_millimeters;
3423 output_info->mm_width = crtc_info->width / pixels_per_mm_horizontal;
3424 output_info->mm_height = crtc_info->height / pixels_per_mm_vertical;
3427 outputAdd(crtc_info, output_info);
3433 free(screen_resources);
3435 return ZAKERO_XENIUM__ERROR(Error_None);
3448 std::error_code Xenium::outputAdd(xcb_randr_crtc_t randr_crtc
3449 , xcb_randr_output_t randr_output
3452 if(randr_crtc == XCB_NONE)
3454 ZAKERO_XENIUM__DEBUG_ERROR(
3455 ZAKERO_XENIUM__ERROR(Error_RandR_Invalid_CRTC_Id)
3458 return ZAKERO_XENIUM__ERROR(Error_RandR_Invalid_CRTC_Id);
3461 if(randr_output == XCB_NONE)
3463 ZAKERO_XENIUM__DEBUG_ERROR(
3464 ZAKERO_XENIUM__ERROR(Error_RandR_Invalid_Output_Id)
3467 return ZAKERO_XENIUM__ERROR(Error_RandR_Invalid_Output_Id);
3470 xcb_generic_error_t* xcb_generic_error =
nullptr;
3472 xcb_randr_get_screen_resources_current_reply_t* screen_resources =
3473 xcb_randr_get_screen_resources_current_reply(this->connection
3474 , xcb_randr_get_screen_resources_current(this->connection
3475 , this->screen->root
3477 , &xcb_generic_error
3480 if(screen_resources ==
nullptr)
3482 ZAKERO_XENIUM__DEBUG_ERROR(
3483 ZAKERO_XENIUM__ERROR(Error_RandR_Screen_Resources_Not_Found)
3486 return ZAKERO_XENIUM__ERROR(Error_RandR_Screen_Resources_Not_Found);
3489 xcb_randr_get_output_info_reply_t* output_info =
3490 xcb_randr_get_output_info_reply(this->connection
3491 , xcb_randr_get_output_info(this->connection
3493 , screen_resources->config_timestamp
3495 , &xcb_generic_error
3498 if(output_info ==
nullptr)
3500 free(screen_resources);
3502 ZAKERO_XENIUM__DEBUG_ERROR(
3503 ZAKERO_XENIUM__ERROR(Error_RandR_Output_Info_Not_Found)
3506 return ZAKERO_XENIUM__ERROR(Error_RandR_Output_Info_Not_Found);
3509 xcb_randr_get_crtc_info_reply_t* crtc_info =
3510 xcb_randr_get_crtc_info_reply(this->connection
3511 , xcb_randr_get_crtc_info(this->connection
3513 , screen_resources->config_timestamp
3515 , &xcb_generic_error
3518 if(crtc_info ==
nullptr)
3521 free(screen_resources);
3523 ZAKERO_XENIUM__DEBUG_ERROR(
3524 ZAKERO_XENIUM__ERROR(Error_RandR_CRTC_Info_Not_Found)
3527 return ZAKERO_XENIUM__ERROR(Error_RandR_CRTC_Info_Not_Found);
3532 if(output_info->mm_width == 0 || output_info->mm_height == 0)
3534 ZAKERO_XENIUM__DEBUG_ERROR(
3535 ZAKERO_XENIUM__ERROR(Error_RandR_Output_Info_Is_Incomplete)
3538 const float pixels_per_mm_horizontal = (float)this->screen->width_in_pixels / this->screen->width_in_millimeters;
3539 const float pixels_per_mm_vertical = (
float)this->screen->height_in_pixels / this->screen->height_in_millimeters;
3541 output_info->mm_width = crtc_info->width / pixels_per_mm_horizontal;
3542 output_info->mm_height = crtc_info->height / pixels_per_mm_vertical;
3545 outputAdd(crtc_info, output_info);
3549 free(screen_resources);
3551 return ZAKERO_XENIUM__ERROR(Error_None);
3561 void Xenium::outputAdd(
const xcb_randr_get_crtc_info_reply_t* crtc_info
3562 ,
const xcb_randr_get_output_info_reply_t* output_info
3565 const std::string output_name(
3566 (
const char*)xcb_randr_get_output_info_name(output_info),
3567 xcb_randr_get_output_info_name_length(output_info)
3570 OutputId output_id = output_info->crtc;
3572 this->output_map[output_id] =
3573 { .name = output_name
3578 , .width = crtc_info->width
3579 , .height = crtc_info->height
3580 , .physical_width_mm = output_info->mm_width
3581 , .physical_height_mm = output_info->mm_height
3582 , .subpixel = output_info->subpixel_order
3585 , .transform = crtc_info->rotation
3586 , .pixels_per_mm_horizontal = (float)crtc_info->width / output_info->mm_width
3587 , .pixels_per_mm_vertical = (
float)crtc_info->height / output_info->mm_height
3590 ZAKERO_XENIUM__DEBUG_VAR(output_id)
3591 ZAKERO_XENIUM__DEBUG_VAR(this->output_map[output_id].name)
3606 std::pair<float, float> Xenium::convertPixelToMm(
const Xenium::Output&
output
3629 std::pair<float, float> Xenium::convertPixelToPercent(
const Xenium::Output&
output
3649 std::pair<int32_t, int32_t> Xenium::convertMmToPixel(
const Xenium::Output&
output
3658 { int32_t(xw * ratio_h)
3659 , int32_t(yh * ratio_v)
3672 std::pair<int32_t, int32_t> Xenium::convertPercentToPixel(
const Xenium::Output&
output
3702 , std::error_code& error
3705 return windowCreate(size, Default_Value_Mask, Default_Value_List, error);
3728 ,
const uint32_t value_mask
3729 , xcb_create_window_value_list_t& value_list
3730 , std::error_code& error
3733 Xenium::WindowCreateData data =
3738 , .atom_close_request = 0
3740 , .size_unit = Xenium::SizeUnit::Millimeter
3741 , .size_mm = size_mm
3742 , .size_percent = {}
3744 , .value_mask = value_mask
3745 , .value_list = value_list
3748 std::future<void> barrier = data.barrier.get_future();
3750 windowCreateAddToQueue(&data);
3758 ZAKERO_XENIUM__DEBUG_ERROR(error);
3765 windowReadyWait(data.window_id);
3788 , std::error_code& error
3791 return windowCreate(size, Default_Value_Mask, Default_Value_List, error);
3813 ,
const uint32_t value_mask
3814 , xcb_create_window_value_list_t& value_list
3815 , std::error_code& error
3818 Xenium::WindowCreateData data =
3823 , .atom_close_request = 0
3825 , .size_unit = Xenium::SizeUnit::Percent
3827 , .size_percent = size_percent
3829 , .value_mask = value_mask
3830 , .value_list = value_list
3833 std::future<void> barrier = data.barrier.get_future();
3835 windowCreateAddToQueue(&data);
3843 ZAKERO_XENIUM__DEBUG_ERROR(error);
3850 windowReadyWait(data.window_id);
3872 , std::error_code& error
3875 return windowCreate(size, Default_Value_Mask, Default_Value_List, error);
3897 ,
const uint32_t value_mask
3898 , xcb_create_window_value_list_t& value_list
3899 , std::error_code& error
3902 Xenium::WindowCreateData data =
3907 , .atom_close_request = 0
3909 , .size_unit = Xenium::SizeUnit::Pixel
3911 , .size_percent = {}
3912 , .size_pixel = size_pixel
3913 , .value_mask = value_mask
3914 , .value_list = value_list
3917 std::future<void> barrier = data.barrier.get_future();
3919 windowCreateAddToQueue(&data);
3927 ZAKERO_XENIUM__DEBUG_ERROR(error);
3934 windowReadyWait(data.window_id);
3949 std::error_code Xenium::windowBorder(
const WindowId window_id
3953 MotifWmHints hints_data =
3956 , .decorations = enable
3961 xcb_void_cookie_t void_cookie =
3962 xcb_change_property_checked(this->connection
3963 , XCB_PROP_MODE_REPLACE
3965 , atom_motif_wm_hints
3966 , atom_motif_wm_hints
3972 xcb_generic_error_t generic_error;
3974 if(requestCheckHasError(void_cookie, generic_error))
3976 ZAKERO_XENIUM__DEBUG_VAR(to_string(generic_error));
3978 return ZAKERO_XENIUM__ERROR(Error_Unknown);
3981 return ZAKERO_XENIUM__ERROR(Error_None);
3988 void Xenium::windowCreateAddToQueue(Xenium::WindowCreateData* window_data
3991 xenium_window_mutex.lock();
3993 window_to_create.push_back(window_data);
3995 xenium_window_mutex.unlock();
4002 void Xenium::windowDestroyAddToQueue(Xenium::WindowDestroyData* window_data
4005 xenium_window_mutex.lock();
4007 window_to_destroy.push_back(window_data);
4009 xenium_window_mutex.unlock();
4022 std::error_code Xenium::windowLocationSet(
const WindowId window_id
4023 ,
const Xenium::PointPixel& point
4026 xcb_configure_window_value_list_t value_list =
4036 xcb_void_cookie_t void_cookie =
4037 xcb_configure_window_aux_checked(this->connection
4040 | XCB_CONFIG_WINDOW_X
4041 | XCB_CONFIG_WINDOW_Y
4045 xcb_generic_error_t generic_error;
4046 if(requestCheckHasError(void_cookie, generic_error))
4048 ZAKERO_XENIUM__DEBUG_VAR(
to_string(generic_error));
4050 return ZAKERO_XENIUM__ERROR(Error_Unknown);
4053 return ZAKERO_XENIUM__ERROR(Error_None);
4068 xcb_client_message_event_t
event =
4069 { .response_type = XCB_CLIENT_MESSAGE
4072 , .window = window_id
4073 , .type = atom_wm_change_state
4076 event.data.data32[0] = XCB_ICCCM_WM_STATE_ICONIC;
4078 xcb_send_event(this->connection
4080 , this->screen->root
4081 , XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY
4082 , (
const char*)&event
4085 xcb_flush(this->connection);
4087 return ZAKERO_XENIUM__ERROR(Error_None);
4105 xcb_client_message_event_t
event =
4106 { .response_type = XCB_CLIENT_MESSAGE
4109 , .window = window_id
4110 , .type = atom_net_wm_state
4114 if(current_mode == Xenium::WindowMode::Normal)
4122 if(current_mode == Xenium::WindowMode::Fullscreen)
4124 event.data.data32[1] = atom_net_wm_state_fullscreen;
4125 event.data.data32[2] = 0;
4129 event.data.data32[1] = atom_net_wm_state_maximized_horz;
4130 event.data.data32[2] = atom_net_wm_state_maximized_vert;
4133 xcb_send_event(this->connection
4135 , this->screen->root
4136 , XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY
4137 , (
const char*)&event
4141 if(new_mode == Xenium::WindowMode::Normal)
4149 if(new_mode == Xenium::WindowMode::Fullscreen)
4151 event.data.data32[1] = atom_net_wm_state_fullscreen;
4152 event.data.data32[2] = 0;
4156 event.data.data32[1] = atom_net_wm_state_maximized_horz;
4157 event.data.data32[2] = atom_net_wm_state_maximized_vert;
4160 xcb_send_event(this->connection
4162 , this->screen->root
4163 , XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY
4164 , (
const char*)&event
4168 xcb_flush(this->connection);
4170 return ZAKERO_XENIUM__ERROR(Error_None);
4185 bool Xenium::windowPropertySet(
WindowId window_id
4186 ,
const xcb_atom_t property
4187 ,
const xcb_atom_t value
4188 , xcb_generic_error_t& generic_error
4191 xcb_void_cookie_t void_cookie =
4192 xcb_change_property_checked(this->connection
4193 , XCB_PROP_MODE_REPLACE
4202 if(requestCheckHasError(void_cookie, generic_error))
4204 ZAKERO_XENIUM__DEBUG_VAR(
to_string(generic_error));
4223 bool Xenium::windowPropertySet(
WindowId window_id
4224 ,
const xcb_atom_t property
4225 ,
const std::string& value
4226 , xcb_generic_error_t& generic_error
4229 xcb_void_cookie_t void_cookie =
4230 xcb_change_property_checked(this->connection
4231 , XCB_PROP_MODE_REPLACE
4239 if(requestCheckHasError(void_cookie, generic_error))
4241 ZAKERO_XENIUM__DEBUG_VAR(
to_string(generic_error));
4259 void Xenium::windowReadySet(
const WindowId window_id
4262 window_ready_map[window_id] =
true;
4275 void Xenium::windowReadyWait(
const WindowId window_id
4278 xcb_map_window(this->connection, window_id);
4279 xcb_flush(this->connection);
4281 while(window_ready_map[window_id] ==
false)
4294 void Xenium::windowResizeTo(
const Output&
output
4295 , Xenium::WindowSizeData& window_size
4296 ,
const xcb_configure_notify_event_t* event
4299 bool update_size =
false;
4301 if(window_size.unit == SizeUnit::Millimeter)
4303 auto pixel = convertMmToPixel(
output
4304 , window_size.mm.
width
4305 , window_size.mm.height
4308 if(pixel.first != window_size.pixel.width
4309 || pixel.second != window_size.pixel.height
4315 window_size.pixel = {pixel.first, pixel.second};
4317 auto percent = convertPixelToPercent(
output
4318 , window_size.pixel.
width
4319 , window_size.pixel.height
4321 window_size.percent = {percent.first, percent.second};
4323 else if(window_size.unit == SizeUnit::Percent)
4325 auto pixel = convertPercentToPixel(
output
4326 , window_size.percent.
width
4327 , window_size.percent.height
4330 if(pixel.first != window_size.pixel.width
4331 || pixel.second != window_size.pixel.height
4335 window_size.pixel = {pixel.first, pixel.second};
4338 auto mm = convertPixelToMm(
output
4339 , window_size.pixel.
width
4340 , window_size.pixel.height
4343 window_size.mm = {mm.first, mm.second};
4347 if(event->width != window_size.pixel.width
4348 || event->height != window_size.pixel.height
4354 window_size.pixel = {
event->width,
event->height};
4356 auto mm = convertPixelToMm(
output
4357 , window_size.pixel.
width
4358 , window_size.pixel.height
4360 window_size.mm = {mm.first, mm.second};
4362 auto percent = convertPixelToPercent(
output
4363 , window_size.pixel.
width
4364 , window_size.pixel.height
4366 window_size.percent = {percent.first, percent.second};
4369 windowSizeSetMinMax(
output, event->window, window_size);
4373 window_size.pixel_lambda(window_size.pixel);
4374 window_size.percent_lambda(window_size.percent);
4375 window_size.mm_lambda(window_size.mm);
4377 windowSizeSet(event->window, window_size.pixel);
4389 std::error_code Xenium::windowSizeSet(
const WindowId window_id
4390 ,
const Xenium::SizePixel& size
4393 xcb_configure_window_value_list_t value_list =
4396 , .width = (uint32_t)size.width
4397 , .height = (uint32_t)size.height
4403 xcb_void_cookie_t void_cookie =
4404 xcb_configure_window_aux_checked(this->connection
4407 | XCB_CONFIG_WINDOW_WIDTH
4408 | XCB_CONFIG_WINDOW_HEIGHT
4412 xcb_generic_error_t generic_error;
4413 if(requestCheckHasError(void_cookie, generic_error))
4415 ZAKERO_XENIUM__DEBUG_VAR(
to_string(generic_error));
4417 return ZAKERO_XENIUM__ERROR(Error_Unknown);
4420 return ZAKERO_XENIUM__ERROR(Error_None);
4432 std::error_code Xenium::windowSizeSetMinMax(
const WindowId window_id
4433 ,
const int32_t min_width
4434 ,
const int32_t min_height
4435 ,
const int32_t max_width
4436 ,
const int32_t max_height
4439 xcb_get_property_cookie_t property_cookie =
4440 xcb_get_property(this->connection
4443 , XCB_ATOM_WM_NORMAL_HINTS
4444 , XCB_ATOM_WM_SIZE_HINTS
4449 xcb_generic_error_t* error_ptr =
nullptr;
4450 xcb_get_property_reply_t* property_reply =
4451 xcb_get_property_reply(this->connection
4457 ZAKERO_XENIUM__DEBUG <<
"Error: " <<
to_string(*error_ptr) <<
'\n';
4459 return ZAKERO_XENIUM__ERROR(Error_Unknown);
4462 xcb_size_hints_t* size_hints =
4463 (xcb_size_hints_t*)xcb_get_property_value(property_reply);
4465 if(min_width == 0 && min_height == 0)
4467 size_hints->flags &= (~XCB_ICCCM_SIZE_HINT_P_MIN_SIZE);
4471 size_hints->flags |= XCB_ICCCM_SIZE_HINT_P_MIN_SIZE;
4474 size_hints->min_width = min_width;
4475 size_hints->min_height = min_height;
4477 if(max_width == 0 && max_height == 0)
4479 size_hints->flags &= (~XCB_ICCCM_SIZE_HINT_P_MAX_SIZE);
4483 size_hints->flags |= XCB_ICCCM_SIZE_HINT_P_MAX_SIZE;
4486 size_hints->max_width = max_width;
4487 size_hints->max_height = max_height;
4489 xcb_void_cookie_t cookie =
4490 xcb_change_property_checked(this->connection
4491 , XCB_PROP_MODE_REPLACE
4493 , XCB_ATOM_WM_NORMAL_HINTS
4494 , XCB_ATOM_WM_SIZE_HINTS
4500 xcb_generic_error_t generic_error;
4502 if(requestCheckHasError(cookie, generic_error))
4504 ZAKERO_XENIUM__DEBUG <<
"Error: " <<
to_string(generic_error) <<
'\n';
4506 return ZAKERO_XENIUM__ERROR(Error_Unknown);
4509 return ZAKERO_XENIUM__ERROR(Error_None);
4531 std::error_code Xenium::windowSizeSetMinMax(
const Xenium::Output&
output
4533 , Xenium::WindowSizeData& window_size
4536 if(window_size.unit == SizeUnit::Millimeter)
4539 auto pixel = convertMmToPixel(
output
4540 , window_size.mm_minimum.
width
4541 , window_size.mm_minimum.height
4543 window_size.pixel_minimum = {pixel.first, pixel.second};
4545 auto percent = convertPixelToPercent(
output
4546 , window_size.pixel_minimum.
width
4547 , window_size.pixel_minimum.height
4549 window_size.percent_minimum = {percent.first, percent.second};
4552 pixel = convertMmToPixel(
output
4553 , window_size.mm_maximum.
width
4554 , window_size.mm_maximum.height
4556 window_size.pixel_maximum = {pixel.first, pixel.second};
4558 percent = convertPixelToPercent(
output
4559 , window_size.pixel_maximum.
width
4560 , window_size.pixel_maximum.height
4562 window_size.percent_maximum = {percent.first, percent.second};
4564 else if(window_size.unit == SizeUnit::Percent)
4567 auto pixel = convertPercentToPixel(
output
4568 , window_size.percent_minimum.
width
4569 , window_size.percent_minimum.height
4571 window_size.pixel_minimum = {pixel.first, pixel.second};
4573 auto mm = convertPixelToMm(
output
4574 , window_size.pixel_minimum.
width
4575 , window_size.pixel_minimum.height
4577 window_size.mm_minimum = {mm.first, mm.second};
4580 pixel = convertPercentToPixel(
output
4581 , window_size.percent_maximum.
width
4582 , window_size.percent_maximum.height
4584 window_size.pixel_maximum = {pixel.first, pixel.second};
4586 mm = convertPixelToMm(
output
4587 , window_size.pixel_maximum.
width
4588 , window_size.pixel_maximum.height
4590 window_size.mm_maximum = {mm.first, mm.second};
4595 auto mm = convertPixelToMm(
output
4596 , window_size.pixel_minimum.
width
4597 , window_size.pixel_minimum.height
4599 window_size.mm_minimum = {mm.first, mm.second};
4601 auto percent = convertPixelToPercent(
output
4602 , window_size.pixel_minimum.
width
4603 , window_size.pixel_minimum.height
4605 window_size.percent_minimum = {percent.first, percent.second};
4608 mm = convertPixelToMm(
output
4609 , window_size.pixel_maximum.
width
4610 , window_size.pixel_maximum.height
4612 window_size.mm_maximum = {mm.first, mm.second};
4614 percent = convertPixelToPercent(
output
4615 , window_size.pixel_maximum.
width
4616 , window_size.pixel_maximum.height
4618 window_size.percent_maximum = {percent.first, percent.second};
4622 std::error_code error;
4624 error = windowSizeSetMinMax(window_id
4625 , window_size.pixel_minimum.width, window_size.pixel_minimum.height
4626 , window_size.pixel_maximum.width, window_size.pixel_maximum.height
4629 # if ZAKERO_XENIUM__DEBUG_ENABLED
4632 ZAKERO_XENIUM__DEBUG_ERROR(error);
4645 void Xenium::xcbEvent(
const xcb_button_press_event_t* event
4650 const WindowId window_id =
event->event;
4652 uint32_t button_code =
event->detail;
4654 if(button_code <= 3 || button_code >= 8)
4660 else if(button_code >= 8)
4669 PointerButton button =
4670 { .code = Pointer_Button_Event_Code[button_code]
4671 , .state =
event->response_type == XCB_BUTTON_PRESS
4672 ? Xenium::PointerButtonState::Pressed
4673 : Xenium::PointerButtonState::Released
4676 OutputId output_id = window_output_map[window_id];
4677 Output
output = output_map.at(output_id);
4679 PointPixel point_pixel = {0,
event->event_x,
event->event_y};
4681 auto mm = convertPixelToMm(
output
4685 PointMm point_mm = {0, mm.first, mm.second};
4687 Xenium::WindowSizeData& window_size = window_size_map[window_id];
4688 PointPercent point_percent =
4690 , (float)event->event_x / (
float)window_size.pixel.width
4691 , (float)event->event_y / (
float)window_size.pixel.height
4694 window_on_button_map[window_id].lambda_mm(button, point_mm, key_modifier);
4695 window_on_button_map[window_id].lambda_percent(button, point_percent, key_modifier);
4696 window_on_button_map[window_id].lambda_pixel(button, point_pixel, key_modifier);
4698 else if(event->response_type == XCB_BUTTON_PRESS)
4700 if(button_code == 4 || button_code == 5)
4702 PointerAxis pointer_axis =
4703 { .time =
event->time
4704 , .steps = button_code == 4 ? -1 : 1
4705 , .distance = button_code == 4 ? -15.0f : 15.0f
4706 , .source = PointerAxisSource::Wheel
4707 , .type = PointerAxisType::Vertical
4710 window_on_axis_map[window_id](pointer_axis, key_modifier);
4712 else if(button_code == 6 || button_code == 7)
4714 PointerAxis pointer_axis =
4715 { .time =
event->time
4716 , .steps = button_code == 6 ? -1 : 1
4717 , .distance = button_code == 6 ? -15.0f : 15.0f
4718 , .source = PointerAxisSource::Wheel
4719 , .type = PointerAxisType::Horizontal
4722 window_on_axis_map[window_id](pointer_axis, key_modifier);
4731 void Xenium::xcbEvent(
const xcb_client_message_event_t* event
4735 if(window_delete_map.contains(event->window))
4737 WindowDeleteData& window_delete = window_delete_map[
event->window];
4738 if(event->data.data32[0] == window_delete.atom_close_request)
4740 window_delete.close_request_lambda();
4769 void Xenium::xcbEvent(
const xcb_configure_notify_event_t* event
4773 if((event->response_type & 0x80) == 0)
4779 const WindowId window_id =
event->window;
4781 auto iter = window_size_map.find(window_id);
4783 if(iter == std::end(window_size_map))
4788 Xenium::WindowSizeData& window_size = iter->second;
4791 const Output&
output = this->
output(event->x, event->y, output_id);
4793 if(window_output_map[window_id] != output_id)
4795 window_output_map[window_id] = output_id;
4797 windowResizeTo(
output, window_size, event);
4802 if(window_size.pixel.width == event->width
4803 && window_size.pixel.height == event->height
4809 window_size.pixel = {
event->width,
event->height};
4811 auto mm = convertPixelToMm(
output
4812 , window_size.pixel.
width
4813 , window_size.pixel.height
4815 window_size.mm = {mm.first, mm.second};
4817 auto percent = convertPixelToPercent(
output
4818 , window_size.pixel.
width
4819 , window_size.pixel.height
4821 window_size.percent = {percent.first, percent.second};
4823 window_size.pixel_lambda(window_size.pixel);
4824 window_size.percent_lambda(window_size.percent);
4825 window_size.mm_lambda(window_size.mm);
4836 void Xenium::xcbEvent(
const xcb_enter_notify_event_t* event
4841 const WindowId window_id =
event->event;
4843 if(event->response_type == XCB_LEAVE_NOTIFY)
4845 window_on_leave_map[window_id]();
4846 window_keyboard[window_id].on_leave();
4850 xkbIndicatorStateUpdate();
4852 OutputId output_id = window_output_map[window_id];
4853 Output
output = output_map.at(output_id);
4855 PointPixel point_pixel = {0,
event->event_x,
event->event_y};
4857 auto mm = convertPixelToMm(
output
4861 PointMm point_mm = {0, mm.first, mm.second};
4863 Xenium::WindowSizeData& window_size = window_size_map[window_id];
4864 PointPercent point_percent =
4866 , (float)event->event_x / (
float)window_size.pixel.width
4867 , (float)event->event_y / (
float)window_size.pixel.height
4870 window_on_enter_map[window_id].lambda_mm(point_mm, key_modifier);
4871 window_on_enter_map[window_id].lambda_percent(point_percent, key_modifier);
4872 window_on_enter_map[window_id].lambda_pixel(point_pixel, key_modifier);
4874 window_keyboard[window_id].on_enter();
4881 void Xenium::xcbEvent(
const xcb_expose_event_t* event
4885 windowReadySet(event->window);
4892 void Xenium::xcbEvent(
const xcb_focus_in_event_t* event
4897 const WindowId window_id =
event->event;
4899 if(window_focus_map.contains(window_id) ==
false)
4904 if(event->response_type == XCB_FOCUS_IN)
4906 xkbControlsUpdate();
4907 xkbIndicatorStateUpdate();
4908 window_focus_map[window_id](
true);
4912 keyDataArrayClear();
4913 window_focus_map[window_id](
false);
4921 void Xenium::xcbEvent(
const xcb_gravity_notify_event_t*
4955 void Xenium::xcbEvent(
const xcb_key_press_event_t* event
4960 uint32_t key_code = (uint32_t)event->detail - 8;
4962 constexpr uint16_t CapsLock = 0b0000'0010'0000'0000;
4963 constexpr uint16_t NumLock = 0b0000'0001'0000'0000;
4964 constexpr uint16_t Alt_Left = 0b0000'0000'1000'0000;
4965 constexpr uint16_t Alt_Right = 0b0000'0000'0100'0000;
4966 constexpr uint16_t Control_Left = 0b0000'0000'0010'0000;
4967 constexpr uint16_t Control_Right = 0b0000'0000'0001'0000;
4968 constexpr uint16_t Meta_Left = 0b0000'0000'0000'1000;
4969 constexpr uint16_t Meta_Right = 0b0000'0000'0000'0100;
4970 constexpr uint16_t Shift_Left = 0b0000'0000'0000'0010;
4971 constexpr uint16_t Shift_Right = 0b0000'0000'0000'0001;
4973 if(event->response_type == XCB_KEY_PRESS)
4978 xkbIndicatorStateUpdate();
4979 xkb_modifier_pressed |= CapsLock;
4983 xkbIndicatorStateUpdate();
4984 xkb_modifier_pressed |= NumLock;
4988 xkb_modifier_pressed |= Alt_Left;
4992 xkb_modifier_pressed |= Alt_Right;
4996 xkb_modifier_pressed |= Control_Left;
5000 xkb_modifier_pressed |= Control_Right;
5004 xkb_modifier_pressed |= Meta_Left;
5008 xkb_modifier_pressed |= Meta_Right;
5012 xkb_modifier_pressed |= Shift_Left;
5015 case KEY_RIGHTSHIFT:
5016 xkb_modifier_pressed |= Shift_Right;
5025 xkbIndicatorStateUpdate();
5026 xkb_modifier_pressed &= (~CapsLock);
5030 xkbIndicatorStateUpdate();
5031 xkb_modifier_pressed &= (~NumLock);
5035 xkb_modifier_pressed &= (~Alt_Left);
5039 xkb_modifier_pressed &= (~Alt_Right);
5043 xkb_modifier_pressed &= (~Control_Left);
5047 xkb_modifier_pressed &= (~Control_Right);
5051 xkb_modifier_pressed &= (~Meta_Left);
5055 xkb_modifier_pressed &= (~Meta_Right);
5059 xkb_modifier_pressed &= (~Shift_Left);
5062 case KEY_RIGHTSHIFT:
5063 xkb_modifier_pressed &= (~Shift_Right);
5068 key_modifier.pressed = 0;
5070 if(xkb_modifier_pressed & CapsLock)
5075 if(xkb_modifier_pressed & NumLock)
5080 if(xkb_modifier_pressed & (Alt_Left | Alt_Right))
5085 if(xkb_modifier_pressed & (Control_Left | Control_Right))
5090 if(xkb_modifier_pressed & (Meta_Left | Meta_Right))
5095 if(xkb_modifier_pressed & (Shift_Left | Shift_Right))
5100 const WindowId window_id =
event->event;
5102 key_data_array[key_code].window_id = window_id;
5104 Key& key = key_data_array[key_code].key;
5105 key.code = key_code;
5107 if(event->response_type == XCB_KEY_PRESS)
5109 key_data_array[key_code].modifier = key_modifier;
5111 if(key.time == event->time)
5113 key.state = KeyState::Repeat;
5117 key.time =
event->time;
5118 key.state = KeyState::Pressed;
5120 key_data_array[key_code].repeat_time =
5121 event->time + xkb_controls.repeat_delay_ms
5124 window_on_key_map[window_id](key, key_modifier);
5136 else if(key.time != 0)
5138 key.time =
event->time;
5139 key.state = KeyState::Released;
5141 key_data_array[key_code].modifier = key_modifier;
5149 void Xenium::xcbEvent(
const xcb_map_notify_event_t*
5159 void Xenium::xcbEvent(
const xcb_motion_notify_event_t* event
5164 const WindowId window_id =
event->event;
5166 OutputId output_id = window_output_map[window_id];
5167 Output
output = output_map.at(output_id);
5169 PointPixel point_pixel = {0,
event->event_x,
event->event_y};
5171 auto mm = convertPixelToMm(
output
5175 PointMm point_mm = {0, mm.first, mm.second};
5177 Xenium::WindowSizeData& window_size = window_size_map[window_id];
5178 PointPercent point_percent =
5180 , (float)event->event_x / (
float)window_size.pixel.width
5181 , (float)event->event_y / (
float)window_size.pixel.height
5184 window_on_motion_map[window_id].lambda_mm(point_mm, key_modifier);
5185 window_on_motion_map[window_id].lambda_percent(point_percent, key_modifier);
5186 window_on_motion_map[window_id].lambda_pixel(point_pixel, key_modifier);
5193 void Xenium::xcbEvent(
const xcb_property_notify_event_t* event
5198 xcb_generic_error_t generic_error;
5200 if(event->atom == atom_net_frame_extents)
5202 std::vector<int32_t> atom_data = Xenium::atomValueData(event->window
5203 , atom_net_frame_extents
5217 { .left = atom_data[0]
5218 , .right = atom_data[1]
5219 , .top = atom_data[2]
5220 , .bottom = atom_data[3]
5223 WindowDecorationsData& window = window_decorations_map[
event->window];
5227 if(frame_extents.left == 0
5228 && frame_extents.right == 0
5229 && frame_extents.top == 0
5230 && frame_extents.bottom == 0
5233 window.window_decorations = WindowDecorations::Client_Side;
5237 window.window_decorations = WindowDecorations::Server_Side;
5240 if(window.window_decorations != window_decorations)
5242 window.lambda(window.window_decorations);
5248 if(event->atom == atom_net_wm_state)
5250 std::vector<xcb_atom_t> value =
5251 atomValueAtom(event->window, event->atom, generic_error);
5253 WindowMode new_window_mode = WindowMode::Normal;
5255 if(zakero::vectorContains(value, atom_net_wm_state_maximized_horz)
5256 && zakero::vectorContains(value, atom_net_wm_state_maximized_vert)
5259 new_window_mode = WindowMode::Maximized;
5261 else if(zakero::vectorContains(value, atom_net_wm_state_fullscreen))
5263 new_window_mode = WindowMode::Fullscreen;
5266 if(window_mode_map.contains(event->window))
5268 WindowModeData& data = window_mode_map[
event->window];
5270 if(data.window_mode != new_window_mode)
5272 data.window_mode = new_window_mode;
5273 lambda = data.lambda;
5276 lambda(new_window_mode);
5286 void Xenium::xcbEvent(
const xcb_reparent_notify_event_t*
5296 void Xenium::xcbEvent(
const xcb_unmap_notify_event_t*
5310 void Xenium::xcbWindowCreate(Xenium::WindowCreateData* window_data
5313 window_data->error = xcbWindowCreateValidate(window_data);
5314 if(window_data->error)
5316 ZAKERO_XENIUM__DEBUG_ERROR(window_data->error);
5321 window_data->error = xcbWindowCreateClient(window_data);
5322 if(window_data->error)
5324 ZAKERO_XENIUM__DEBUG_ERROR(window_data->error);
5326 Xenium::WindowDestroyData data =
5328 , .window_id = window_data->window_id
5329 , .gc = window_data->gc
5332 xcbWindowDestroy(&data);
5337 window_data->error = xcbWindowCreateInit(window_data);
5338 if(window_data->error)
5340 ZAKERO_XENIUM__DEBUG_ERROR(window_data->error);
5342 Xenium::WindowDestroyData data =
5344 , .window_id = window_data->window_id
5345 , .gc = window_data->gc
5348 xcbWindowDestroy(&data);
5364 std::error_code Xenium::xcbWindowCreateValidate(Xenium::WindowCreateData* window_data
5367 window_data->output_id = output_map.begin()->first;
5368 Xenium::Output&
output = output_map.begin()->second;
5370 Xenium::SizePixel size_pixel;
5372 if(window_data->size_unit == Xenium::SizeUnit::Millimeter)
5374 auto pixel = convertMmToPixel(
output
5375 , window_data->size_mm.
width
5376 , window_data->size_mm.height
5378 size_pixel = {pixel.first, pixel.second};
5380 else if(window_data->size_unit == Xenium::SizeUnit::Percent)
5382 auto pixel = convertPercentToPixel(
output
5383 , window_data->size_percent.
width
5384 , window_data->size_percent.height
5386 size_pixel = {pixel.first, pixel.second};
5390 size_pixel = window_data->size_pixel;
5393 if((size_pixel.width < Window_Size_Minimum)
5394 || (size_pixel.width < Window_Size_Minimum)
5397 ZAKERO_XENIUM__DEBUG_ERROR(
5398 ZAKERO_XENIUM__ERROR(Error_Window_Size_Too_Small)
5401 return ZAKERO_XENIUM__ERROR(Error_Window_Size_Too_Small);
5404 if(window_data->size_unit == Xenium::SizeUnit::Millimeter)
5406 window_data->size_pixel = size_pixel;
5408 auto percent = convertPixelToPercent(
output
5409 , window_data->size_pixel.
width
5410 , window_data->size_pixel.height
5412 window_data->size_percent = {percent.first, percent.second};
5414 else if(window_data->size_unit == Xenium::SizeUnit::Percent)
5416 window_data->size_pixel = size_pixel;
5418 auto mm = convertPixelToMm(
output
5419 , window_data->size_pixel.
width
5420 , window_data->size_pixel.height
5422 window_data->size_mm = {mm.first, mm.second};
5426 auto mm = convertPixelToMm(
output
5427 , window_data->size_pixel.
width
5428 , window_data->size_pixel.height
5430 window_data->size_mm = {mm.first, mm.second};
5432 auto percent = convertPixelToPercent(
output
5433 , window_data->size_pixel.
width
5434 , window_data->size_pixel.height
5436 window_data->size_percent = {percent.first, percent.second};
5439 return ZAKERO_XENIUM__ERROR(Error_None);
5450 std::error_code Xenium::xcbWindowCreateClient(Xenium::WindowCreateData* data
5453 data->window_id = xcb_generate_id(this->connection);
5455 xcb_void_cookie_t cookie =
5456 xcb_create_window_aux_checked(this->connection
5457 , this->screen->root_depth
5459 , this->screen->root
5461 , data->size_pixel.width
5462 , data->size_pixel.height
5464 , XCB_WINDOW_CLASS_INPUT_OUTPUT
5465 , this->screen->root_visual
5470 xcb_generic_error_t generic_error;
5472 if(requestCheckHasError(cookie, generic_error))
5474 ZAKERO_XENIUM__DEBUG <<
"Error: " <<
to_string(generic_error) <<
'\n';
5476 data->window_id = 0;
5478 return ZAKERO_XENIUM__ERROR(Error_Unknown);
5481 data->atom_close_request = atomCreateDeleteWindow(data->window_id
5485 if(data->atom_close_request == XCB_ATOM_NONE)
5487 ZAKERO_XENIUM__DEBUG <<
"Error: " <<
to_string(generic_error) <<
'\n';
5489 return ZAKERO_XENIUM__ERROR(Error_Unknown);
5492 xcb_size_hints_t size_hints =
5504 , .min_aspect_num = 0
5505 , .min_aspect_den = 0
5506 , .max_aspect_num = 0
5507 , .max_aspect_den = 0
5513 xcb_change_property_checked(this->connection
5514 , XCB_PROP_MODE_REPLACE
5516 , XCB_ATOM_WM_NORMAL_HINTS
5517 , XCB_ATOM_WM_SIZE_HINTS
5523 if(requestCheckHasError(cookie, generic_error))
5525 ZAKERO_XENIUM__DEBUG <<
"Error: " <<
to_string(generic_error) <<
'\n';
5527 return ZAKERO_XENIUM__ERROR(Error_Unknown);
5530 data->gc = xcb_generate_id(this->connection);
5531 cookie = xcb_create_gc_checked(this->connection
5538 if(requestCheckHasError(cookie, generic_error))
5540 ZAKERO_XENIUM__DEBUG <<
"Error: " <<
to_string(generic_error) <<
'\n';
5544 return ZAKERO_XENIUM__ERROR(Error_Unknown);
5547 return ZAKERO_XENIUM__ERROR(Error_None);
5554 void Xenium::xcbWindowDestroy(Xenium::WindowDestroyData* window_data
5557 if(window_data->window_id == 0)
5562 if(window_data->gc != 0)
5564 xcb_free_gc(this->connection, window_data->gc);
5566 window_data->gc = 0;
5569 xcb_destroy_window(this->connection, window_data->window_id);
5571 window_decorations_map.erase(window_data->window_id);
5572 window_delete_map.erase(window_data->window_id);
5573 window_focus_map.erase(window_data->window_id);
5574 window_keyboard.erase(window_data->window_id);
5575 window_map.erase(window_data->window_id);
5576 window_mode_map.erase(window_data->window_id);
5577 window_on_axis_map.erase(window_data->window_id);
5578 window_on_button_map.erase(window_data->window_id);
5579 window_on_enter_map.erase(window_data->window_id);
5580 window_on_key_map.erase(window_data->window_id);
5581 window_on_leave_map.erase(window_data->window_id);
5582 window_on_motion_map.erase(window_data->window_id);
5583 window_output_map.erase(window_data->window_id);
5584 window_ready_map.erase(window_data->window_id);
5585 window_size_map.erase(window_data->window_id);
5587 window_data->window_id = 0;
5598 std::error_code Xenium::xcbWindowCreateInit(Xenium::WindowCreateData* data
5601 window_size_map[data->window_id] =
5602 { .mm = data->size_mm
5603 , .mm_minimum = {0, 0}
5604 , .mm_maximum = {0, 0}
5605 , .mm_lambda = LambdaSizeMm_DoNothing
5606 , .percent = data->size_percent
5607 , .percent_minimum = {0, 0}
5608 , .percent_maximum = {0, 0}
5609 , .percent_lambda = LambdaSizePercent_DoNothing
5610 , .pixel = data->size_pixel
5611 , .pixel_minimum = {0, 0}
5612 , .pixel_maximum = {0, 0}
5613 , .pixel_lambda = LambdaSizePixel_DoNothing
5614 , .unit = data->size_unit
5617 window_mode_map[data->window_id] =
5618 { .window_mode = WindowMode::Normal
5619 , .lambda = LambdaWindowMode_DoNothing
5622 window_output_map[data->window_id] = data->output_id;
5624 window_keyboard[data->window_id] =
5625 { .on_enter = Lambda_DoNothing
5626 , .on_leave = Lambda_DoNothing
5629 window_on_key_map[data->window_id] = LambdaKey_DoNothing;
5630 window_on_leave_map[data->window_id] = Lambda_DoNothing;
5631 window_on_axis_map[data->window_id] = LambdaAxis_DoNothing;
5633 window_on_motion_map[data->window_id] =
5634 { .lambda_mm = LambdaPointMm_DoNothing
5635 , .lambda_percent = LambdaPointPercent_DoNothing
5636 , .lambda_pixel = LambdaPointPixel_DoNothing
5639 window_on_button_map[data->window_id] =
5640 { .lambda_mm = LambdaButtonMm_DoNothing
5641 , .lambda_percent = LambdaButtonPercent_DoNothing
5642 , .lambda_pixel = LambdaButtonPixel_DoNothing
5645 window_on_enter_map[data->window_id] =
5646 { .lambda_mm = LambdaPointMm_DoNothing
5647 , .lambda_percent = LambdaPointPercent_DoNothing
5648 , .lambda_pixel = LambdaPointPixel_DoNothing
5651 window_decorations_map[data->window_id] =
5652 { .window_decorations = WindowDecorations::Server_Side
5653 , .lambda = LambdaWindowDecorations_DoNothing
5656 window_focus_map[data->window_id] = LambdaBool_DoNothing;
5658 window_delete_map[data->window_id] =
5659 { .close_request_lambda = Lambda_DoNothing
5660 , .atom_close_request = data->atom_close_request
5663 window_ready_map[data->window_id] =
false;
5665 return ZAKERO_XENIUM__ERROR(Error_None);
5679 std::error_code Xenium::atomInit() noexcept
5681 auto cookie_motif_wm_hints = internAtomRequest(
"_MOTIF_WM_HINTS");
5682 auto cookie_net_frame_extents = internAtomRequest(
"_NET_FRAME_EXTENTS");
5683 auto cookie_net_wm_state = internAtomRequest(
"_NET_WM_STATE");
5684 auto cookie_net_wm_state_fullscreen = internAtomRequest(
"_NET_WM_STATE_FULLSCREEN");
5685 auto cookie_net_wm_state_hidden = internAtomRequest(
"_NET_WM_STATE_HIDDEN");
5686 auto cookie_net_wm_state_maximized_horz = internAtomRequest(
"_NET_WM_STATE_MAXIMIZED_HORZ");
5687 auto cookie_net_wm_state_maximized_vert = internAtomRequest(
"_NET_WM_STATE_MAXIMIZED_VERT");
5688 auto cookie_wm_change_state = internAtomRequest(
"WM_CHANGE_STATE");
5689 auto cookie_wm_delete_window = internAtomRequest(
"WM_DELETE_WINDOW");
5690 auto cookie_wm_protocols = internAtomRequest(
"WM_PROTOCOLS");
5692 xcb_generic_error_t generic_error;
5694 atom_motif_wm_hints = internAtomReply(cookie_motif_wm_hints , generic_error);
5695 atom_net_frame_extents = internAtomReply(cookie_net_frame_extents , generic_error);
5696 atom_net_wm_state = internAtomReply(cookie_net_wm_state , generic_error);
5697 atom_net_wm_state_fullscreen = internAtomReply(cookie_net_wm_state_fullscreen , generic_error);
5698 atom_net_wm_state_hidden = internAtomReply(cookie_net_wm_state_hidden , generic_error);
5699 atom_net_wm_state_maximized_horz = internAtomReply(cookie_net_wm_state_maximized_horz , generic_error);
5700 atom_net_wm_state_maximized_vert = internAtomReply(cookie_net_wm_state_maximized_vert , generic_error);
5701 atom_wm_change_state = internAtomReply(cookie_wm_change_state , generic_error);
5702 atom_wm_delete_window = internAtomReply(cookie_wm_delete_window , generic_error);
5703 atom_wm_protocols = internAtomReply(cookie_wm_protocols , generic_error);
5705 if(atom_wm_delete_window == XCB_ATOM_NONE)
5707 ZAKERO_XENIUM__DEBUG_ERROR(
5708 ZAKERO_XENIUM__ERROR(Error_Xcb_WM_Delete_Window_Not_Available)
5711 return ZAKERO_XENIUM__ERROR(Error_Xcb_WM_Delete_Window_Not_Available);
5714 if(atom_wm_protocols == XCB_ATOM_NONE)
5716 ZAKERO_XENIUM__DEBUG_ERROR(
5717 ZAKERO_XENIUM__ERROR(Error_Xcb_WM_Protocols_Not_Available)
5720 return ZAKERO_XENIUM__ERROR(Error_Xcb_WM_Protocols_Not_Available);
5723 if(atom_net_wm_state == XCB_ATOM_NONE)
5725 ZAKERO_XENIUM__DEBUG_ERROR(
5726 ZAKERO_XENIUM__ERROR(Error_Xcb_NETWM_State_Not_Available)
5729 return ZAKERO_XENIUM__ERROR(Error_Xcb_NETWM_State_Not_Available);
5732 if(atom_net_wm_state_fullscreen == XCB_ATOM_NONE)
5734 ZAKERO_XENIUM__DEBUG_ERROR(
5735 ZAKERO_XENIUM__ERROR(Error_Xcb_Fullscreen_Not_Available)
5738 return ZAKERO_XENIUM__ERROR(Error_Xcb_Fullscreen_Not_Available);
5741 if(atom_net_wm_state_hidden == XCB_ATOM_NONE)
5743 ZAKERO_XENIUM__DEBUG_ERROR(
5744 ZAKERO_XENIUM__ERROR(Error_Xcb_Hidden_Not_Available)
5747 return ZAKERO_XENIUM__ERROR(Error_Xcb_Hidden_Not_Available);
5750 if((atom_net_wm_state_maximized_horz == XCB_ATOM_NONE)
5751 || (atom_net_wm_state_maximized_vert == XCB_ATOM_NONE)
5754 ZAKERO_XENIUM__DEBUG_ERROR(
5755 ZAKERO_XENIUM__ERROR(Error_Xcb_Maximized_Window_Not_Available)
5758 return ZAKERO_XENIUM__ERROR(Error_Xcb_Maximized_Window_Not_Available);
5761 return ZAKERO_XENIUM__ERROR(Error_None);
5778 xcb_atom_t Xenium::atomCreateDeleteWindow(
const WindowId window_id
5779 , xcb_generic_error_t& generic_error
5782 bool property_was_set = windowPropertySet(window_id
5784 , atom_wm_delete_window
5788 if(property_was_set ==
false)
5790 ZAKERO_XENIUM__DEBUG_VAR(
to_string(generic_error));
5791 return XCB_ATOM_NONE;
5794 return atom_wm_delete_window;
5809 std::string Xenium::atomName(
const xcb_atom_t atom
5812 if(atom == XCB_ATOM_NONE)
5817 xcb_get_atom_name_cookie_t cookie =
5818 xcb_get_atom_name(this->connection, atom);
5820 xcb_generic_error_t* error =
nullptr;
5822 xcb_get_atom_name_reply_t* reply =
5823 xcb_get_atom_name_reply(this->connection
5828 if(reply ==
nullptr)
5833 char* name = xcb_get_atom_name_name(reply);
5835 std::string atom_name(name);
5855 std::vector<xcb_atom_t> Xenium::atomValueAtom(
const WindowId window_id
5856 ,
const xcb_atom_t property_atom
5857 , xcb_generic_error_t& generic_error
5860 xcb_get_property_cookie_t property_cookie =
5861 xcb_get_property(this->connection
5870 xcb_generic_error_t* error =
nullptr;
5872 xcb_get_property_reply_t*
property =
5873 xcb_get_property_reply(this->connection
5878 if(property ==
nullptr)
5880 generic_error = *error;
5885 int length = xcb_get_property_value_length(property) / 4;
5887 std::vector<xcb_atom_t> retval(length);
5889 xcb_atom_t* value = (xcb_atom_t*)xcb_get_property_value(property);
5891 for(
int i = 0; i < length; i++)
5893 retval[i] = value[i];
5919 std::vector<int32_t> Xenium::atomValueData(
const WindowId window_id
5920 ,
const xcb_atom_t property_atom
5921 ,
const xcb_atom_t type
5922 ,
const size_t count
5923 , xcb_generic_error_t& generic_error
5926 xcb_get_property_cookie_t property_cookie =
5927 xcb_get_property(this->connection
5936 xcb_generic_error_t* error =
nullptr;
5938 xcb_get_property_reply_t*
property =
5939 xcb_get_property_reply(this->connection
5944 if(property ==
nullptr)
5946 generic_error = *error;
5951 int length = xcb_get_property_value_length(property) / 4;
5953 std::vector<int32_t> vector(length);
5955 int32_t* value = (int32_t*)xcb_get_property_value(property);
5957 for(
int i = 0; i < length; i++)
5959 vector[i] = value[i];
5986 xcb_atom_t Xenium::internAtom(
const std::string& atom_name
5987 ,
const bool create_if_needed
5988 , xcb_generic_error_t& generic_error
5991 xcb_generic_error_t* error =
nullptr;
5993 xcb_intern_atom_reply_t* atom_reply =
5994 xcb_intern_atom_reply(this->connection
5995 , xcb_intern_atom(this->connection
5998 , create_if_needed ? 0 : 1
5999 , atom_name.length()
6007 if(error !=
nullptr)
6009 atom = XCB_ATOM_NONE;
6010 generic_error = *error;
6013 ZAKERO_XENIUM__DEBUG <<
"Error: " <<
to_string(generic_error) <<
'\n';
6015 else if(atom_reply->atom == XCB_ATOM_NONE
6016 && atom_name !=
"XCB_ATOM_NONE"
6019 ZAKERO_XENIUM__DEBUG <<
"Error: Failed to get \""
6024 atom = XCB_ATOM_NONE;
6028 atom = atom_reply->atom;
6051 xcb_intern_atom_cookie_t Xenium::internAtomRequest(
const std::string& atom_name
6052 ,
const bool create_if_needed
6055 xcb_intern_atom_cookie_t cookie =
6056 xcb_intern_atom(this->connection
6060 , atom_name.length()
6079 xcb_atom_t Xenium::internAtomReply(
const xcb_intern_atom_cookie_t intern_atom_cookie
6080 , xcb_generic_error_t& generic_error
6083 xcb_generic_error_t* error =
nullptr;
6085 xcb_intern_atom_reply_t* atom_reply =
6086 xcb_intern_atom_reply(this->connection
6087 , intern_atom_cookie
6093 if(error !=
nullptr)
6095 atom = XCB_ATOM_NONE;
6096 generic_error = *error;
6099 ZAKERO_XENIUM__DEBUG <<
"Error: " <<
to_string(generic_error) <<
'\n';
6101 else if(atom_reply->atom == XCB_ATOM_NONE)
6103 ZAKERO_XENIUM__DEBUG <<
"Error: Failed to get atom.\n";
6105 atom = XCB_ATOM_NONE;
6109 atom = atom_reply->atom;
6128 std::error_code Xenium::randrInit() noexcept
6130 const xcb_query_extension_reply_t* randr =
6131 xcb_get_extension_data(this->connection, &xcb_randr_id);
6133 if(randr->present == 0)
6135 ZAKERO_XENIUM__DEBUG_ERROR(
6136 ZAKERO_XENIUM__ERROR(Error_RandR_Not_Available)
6139 return ZAKERO_XENIUM__ERROR(Error_RandR_Not_Available);
6142 randr_error_base = randr->first_error;
6143 randr_event_base = randr->first_event;
6145 xcb_generic_error_t* xcb_generic_error =
nullptr;
6147 xcb_randr_query_version_reply_t* randr_query_version =
6148 xcb_randr_query_version_reply(this->connection
6149 , xcb_randr_query_version(this->connection
6150 , std::numeric_limits<uint32_t>::max()
6151 , std::numeric_limits<uint32_t>::max()
6153 , &xcb_generic_error
6156 randr_query_version_major = randr_query_version->major_version;
6157 randr_query_version_minor = randr_query_version->minor_version;
6161 if(randr_query_version_major < 1
6162 || (randr_query_version_major == 1
6163 && randr_query_version_minor < 1
6167 ZAKERO_XENIUM__DEBUG_ERROR(
6168 ZAKERO_XENIUM__ERROR(Error_RandR_Version_Too_Old)
6171 return ZAKERO_XENIUM__ERROR(Error_RandR_Version_Too_Old);
6174 xcb_randr_select_input(this->connection
6175 , this->screen->root
6177 | XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE
6178 | XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE
6188 return ZAKERO_XENIUM__ERROR(Error_None);
6195 void Xenium::randrEvent(
const xcb_randr_crtc_change_t* event
6199 OutputId output_id =
event->crtc;
6201 if(this->screen->root != event->window
6202 || output_map.contains(output_id) ==
false
6208 Output&
output = output_map[output_id];
6229 output_on_change(output_id);
6236 void Xenium::randrEvent(
const xcb_randr_output_change_t* event
6241 if(this->screen->root != event->window)
6246 OutputId output_id =
event->crtc;
6248 if(event->connection == XCB_RANDR_CONNECTION_DISCONNECTED)
6250 if(output_map.contains(output_id))
6252 output_on_remove(output_id);
6255 std::lock_guard<std::mutex> lock(output_mutex);
6257 output_map.erase(output_id);
6259 else if((event->connection == XCB_RANDR_CONNECTION_CONNECTED)
6260 || (output_map.contains(output_id) ==
false)
6263 std::error_code error;
6265 std::lock_guard<std::mutex> lock(output_mutex);
6267 error = outputAdd(event->crtc, event->output);
6272 output_on_add(output_id);
6274 # if ZAKERO_XENIUM__DEBUG_ENABLED
6277 ZAKERO_XENIUM__DEBUG_ERROR(error);
6284 Output&
output = output_map[output_id];
6293 output_on_change(output_id);
6305 void Xenium::randrEvent(
const xcb_randr_notify_event_t* event
6308 switch(event->subCode)
6310 case XCB_RANDR_NOTIFY_CRTC_CHANGE:
6311 randrEvent(&event->u.cc);
6313 case XCB_RANDR_NOTIFY_OUTPUT_CHANGE:
6314 randrEvent(&event->u.oc);
6316 case XCB_RANDR_NOTIFY_OUTPUT_PROPERTY:
6319 case XCB_RANDR_NOTIFY_PROVIDER_CHANGE:
6322 case XCB_RANDR_NOTIFY_PROVIDER_PROPERTY:
6325 case XCB_RANDR_NOTIFY_RESOURCE_CHANGE:
6328 case XCB_RANDR_NOTIFY_LEASE:
6332 fprintf(stderr,
"Unhandled Sub-Event %d\n", event->subCode);
6340 void Xenium::randrEvent(
const xcb_randr_screen_change_notify_event_t*
6356 std::error_code Xenium::xkbInit() noexcept
6358 xcb_xkb_use_extension_reply_t* extension_reply =
6359 xcb_xkb_use_extension_reply(this->connection
6360 , xcb_xkb_use_extension(this->connection, 1, 0)
6364 if(extension_reply ==
nullptr)
6366 ZAKERO_XENIUM__DEBUG_ERROR(
6367 ZAKERO_XENIUM__ERROR(Error_Xcb_Xkb_Not_Available)
6370 return ZAKERO_XENIUM__ERROR(Error_Xcb_Xkb_Not_Available);
6373 free(extension_reply);
6375 return ZAKERO_XENIUM__ERROR(Error_None);
6386 void Xenium::keyDataArrayClear() noexcept
6390 for(
auto& key_data : key_data_array)
6392 Key& key = key_data.key;
6399 key.state = KeyState::Released;
6400 key.time = time_now;
6402 const KeyModifier& modifier = key_data.modifier;
6403 const WindowId& window_id = key_data.window_id;
6405 window_on_key_map[window_id](key, modifier);
6420 void Xenium::keyDataArrayProcess() noexcept
6422 for(
auto& key_data : key_data_array)
6424 Key& key = key_data.key;
6431 if(key.state == KeyState::Pressed)
6433 key.state = KeyState::Repeat;
6438 const WindowId& window_id = key_data.window_id;
6440 if(key.state == KeyState::Released)
6442 window_on_key_map[window_id](key, key_data.modifier);
6448 auto& repeat_time = key_data.repeat_time;
6452 if(key.state == KeyState::Repeat
6453 && repeat_time < time_now
6456 window_on_key_map[window_id](key, key_modifier);
6457 key.time = repeat_time;
6458 repeat_time += xkb_controls.repeat_interval_ms;
6469 void Xenium::xkbControlsUpdate() noexcept
6471 xcb_xkb_get_controls_reply_t* controls_reply =
6472 xcb_xkb_get_controls_reply(this->connection
6473 , xcb_xkb_get_controls(this->connection
6474 , XCB_XKB_ID_USE_CORE_KBD
6479 if(controls_reply ==
nullptr)
6484 xkb_controls.repeat_delay_ms = controls_reply->repeatDelay;
6485 xkb_controls.repeat_interval_ms = controls_reply->repeatInterval;
6487 free(controls_reply);
6494 void Xenium::xkbIndicatorStateUpdate() noexcept
6496 xcb_xkb_get_indicator_state_reply_t* reply =
6497 xcb_xkb_get_indicator_state_reply(this->connection
6498 , xcb_xkb_get_indicator_state(this->connection
6499 , XCB_XKB_ID_USE_CORE_KBD
6504 if(reply ==
nullptr)
6509 const uint32_t state = reply->state;
6513 key_modifier.locked = 0
6514 | (bool(state & XCB_XKB_INDICATOR_STATE_CAPSLOCK) * caps_lock)
6515 | (
bool(state & XCB_XKB_INDICATOR_STATE_NUMLOCK) * num_lock)
6537 bool Xenium::requestCheckHasError(
const xcb_void_cookie_t& void_cookie
6538 , xcb_generic_error_t& generic_error
6541 xcb_generic_error_t* error = xcb_request_check(this->connection, void_cookie);
6543 if(error !=
nullptr)
6545 std::cout <<
"requestCheck Error: " <<
to_string(*error) <<
'\n';
6547 generic_error = *error;
6662 , frame_buffer(nullptr)
6663 , frame_buffer_size{0, 0}
6664 , window_id(((WindowCreateData*)data)->window_id)
6665 , gc(((WindowCreateData*)data)->gc)
6666 , frame_buffer_length(0)
6677 Xenium::WindowDestroyData data =
6679 , .window_id = this->window_id
6683 std::future<void> barrier = data.barrier.get_future();
6685 xenium->windowDestroyAddToQueue(&data);
6718 xcb_generic_error_t generic_error;
6720 success = xenium->windowPropertySet(window_id
6726 if(success ==
false)
6728 ZAKERO_XENIUM__DEBUG_VAR(
to_string(generic_error));
6743 xcb_generic_error_t generic_error;
6745 success = xenium->windowPropertySet(window_id
6751 if(success ==
false)
6753 ZAKERO_XENIUM__DEBUG_VAR(
to_string(generic_error));
6774 WindowDeleteData& window_delete = xenium->window_delete_map[window_id];
6776 if(lambda ==
nullptr)
6778 window_delete.close_request_lambda = Lambda_DoNothing;
6782 window_delete.close_request_lambda = lambda;
6803 if(lambda ==
nullptr)
6805 xenium->window_focus_map[window_id] = LambdaBool_DoNothing;
6809 xenium->window_focus_map[window_id] = lambda;
6834 std::error_code error;
6836 if(decorations == WindowDecorations::Client_Side)
6839 error = xenium->windowBorder(window_id,
false);
6844 error = xenium->windowBorder(window_id,
true);
6847 # if ZAKERO_XENIUM__DEBUG_ENABLED
6850 ZAKERO_XENIUM__DEBUG_ERROR(error);
6868 WindowDecorationsData& window_decorations = xenium->window_decorations_map[window_id];
6872 window_decorations.lambda = lambda;
6876 window_decorations.lambda = LambdaWindowDecorations_DoNothing;
6903 std::lock_guard lock(xenium->output_mutex);
6905 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
6907 Xenium::WindowSizeData& window_size = xenium->window_size_map[window_id];
6908 window_size.unit = SizeUnit::Millimeter;
6910 auto pixel = xenium->convertMmToPixel(
output
6915 if(pixel.first < Window_Size_Minimum
6916 || pixel.second < Window_Size_Minimum
6919 return ZAKERO_XENIUM__ERROR(Error_Window_Size_Too_Small);
6922 if(pixel.first == window_size.pixel.width
6923 && pixel.second == window_size.pixel.height
6926 return ZAKERO_XENIUM__ERROR(Error_None);
6929 SizePixel size_pixel = {pixel.first, pixel.second};
6931 std::error_code error = xenium->windowSizeSet(window_id, size_pixel);
6933 # if ZAKERO_XENIUM__DEBUG_ENABLED
6936 ZAKERO_XENIUM__DEBUG_ERROR(error);
6964 std::lock_guard lock(xenium->output_mutex);
6966 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
6968 Xenium::WindowSizeData& window_size = xenium->window_size_map[window_id];
6969 window_size.unit = SizeUnit::Percent;
6971 auto pixel = xenium->convertPercentToPixel(
output
6976 if(pixel.first < Window_Size_Minimum
6977 || pixel.second < Window_Size_Minimum
6980 return ZAKERO_XENIUM__ERROR(Error_Window_Size_Too_Small);
6983 if(pixel.first == window_size.pixel.width
6984 && pixel.second == window_size.pixel.height
6987 return ZAKERO_XENIUM__ERROR(Error_None);
6990 SizePixel size_pixel = {pixel.first, pixel.second};
6992 std::error_code error = xenium->windowSizeSet(window_id, size_pixel);
6994 # if ZAKERO_XENIUM__DEBUG_ENABLED
6997 ZAKERO_XENIUM__DEBUG_ERROR(error);
7024 if(size.width < Window_Size_Minimum
7025 || size.height < Window_Size_Minimum
7028 return ZAKERO_XENIUM__ERROR(Error_Window_Size_Too_Small);
7031 Xenium::WindowSizeData& window_size = xenium->window_size_map[window_id];
7032 window_size.unit = Xenium::SizeUnit::Pixel;
7034 if(window_size.pixel.width == size.width
7035 && window_size.pixel.height == size.height
7038 return ZAKERO_XENIUM__ERROR(Error_None);
7041 std::error_code error = xenium->windowSizeSet(window_id, size);
7043 # if ZAKERO_XENIUM__DEBUG_ENABLED
7046 ZAKERO_XENIUM__DEBUG_ERROR(error);
7069 std::error_code error;
7071 error = validateMinMax<Xenium::SizeMm>(size_min, size_max);
7074 ZAKERO_XENIUM__DEBUG_ERROR(error);
7079 std::lock_guard lock(xenium->output_mutex);
7081 Xenium::WindowSizeData& window_size = xenium->window_size_map[window_id];
7083 window_size.unit = Xenium::SizeUnit::Millimeter;
7084 window_size.mm_minimum = size_min;
7085 window_size.mm_maximum = size_max;
7087 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7089 error = xenium->windowSizeSetMinMax(
output, window_id, window_size);
7091 # if ZAKERO_XENIUM__DEBUG_ENABLED
7094 ZAKERO_XENIUM__DEBUG_ERROR(error);
7117 std::error_code error;
7119 error = validateMinMax<Xenium::SizePercent>(size_min, size_max);
7122 ZAKERO_XENIUM__DEBUG_ERROR(error);
7127 std::lock_guard lock(xenium->output_mutex);
7129 Xenium::WindowSizeData& window_size = xenium->window_size_map[window_id];
7131 window_size.unit = Xenium::SizeUnit::Percent;
7132 window_size.percent_minimum = size_min;
7133 window_size.percent_maximum = size_max;
7135 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7137 error = xenium->windowSizeSetMinMax(
output, window_id, window_size);
7139 # if ZAKERO_XENIUM__DEBUG_ENABLED
7142 ZAKERO_XENIUM__DEBUG_ERROR(error);
7165 std::error_code error;
7167 error = validateMinMax<Xenium::SizePixel>(size_min, size_max);
7170 ZAKERO_XENIUM__DEBUG_ERROR(error);
7175 std::lock_guard lock(xenium->output_mutex);
7177 Xenium::WindowSizeData& window_size = xenium->window_size_map[window_id];
7179 window_size.unit = Xenium::SizeUnit::Pixel;
7180 window_size.pixel_minimum = size_min;
7181 window_size.pixel_maximum = size_max;
7183 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7185 error = xenium->windowSizeSetMinMax(
output, window_id, window_size);
7187 # if ZAKERO_XENIUM__DEBUG_ENABLED
7190 ZAKERO_XENIUM__DEBUG_ERROR(error);
7214 Xenium::WindowSizeData& window_size = xenium->window_size_map[window_id];
7218 window_size.mm_lambda = lambda;
7222 window_size.mm_lambda = LambdaSizeMm_DoNothing;
7243 Xenium::WindowSizeData& window_size = xenium->window_size_map[window_id];
7247 window_size.percent_lambda = lambda;
7251 window_size.percent_lambda = LambdaSizePercent_DoNothing;
7272 Xenium::WindowSizeData& window_size = xenium->window_size_map[window_id];
7276 window_size.pixel_lambda = lambda;
7280 window_size.pixel_lambda = LambdaSizePixel_DoNothing;
7297 std::lock_guard lock(xenium->output_mutex);
7299 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7301 auto value = xenium->convertPixelToMm(
output, point.
x, point.y);
7303 return {0, value.first, value.second};
7317 std::lock_guard lock(xenium->output_mutex);
7319 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7321 auto value = xenium->convertPixelToPercent(
output, point.
x, point.y);
7323 return {0, value.first, value.second};
7337 std::lock_guard lock(xenium->output_mutex);
7339 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7341 auto value = xenium->convertMmToPixel(
output, point.
x, point.y);
7343 return {0, value.first, value.second};
7357 std::lock_guard lock(xenium->output_mutex);
7359 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7361 auto value = xenium->convertPercentToPixel(
output, point.
x, point.y);
7363 return {0, value.first, value.second};
7378 std::lock_guard lock(xenium->output_mutex);
7380 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7382 auto value = xenium->convertPixelToMm(
output, size.
width, size.height);
7384 return {value.first, value.second};
7398 std::lock_guard lock(xenium->output_mutex);
7400 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7402 auto value = xenium->convertPixelToPercent(
output, size.
width, size.height);
7404 return {value.first, value.second};
7418 std::lock_guard lock(xenium->output_mutex);
7420 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7422 auto value = xenium->convertMmToPixel(
output, size.
width, size.height);
7424 return {value.first, value.second};
7438 std::lock_guard lock(xenium->output_mutex);
7440 Output&
output = xenium->output_map[xenium->window_output_map[window_id]];
7442 auto value = xenium->convertPercentToPixel(
output, size.
width, size.height);
7444 return {value.first, value.second};
7460 return xenium->window_mode_map[window_id].window_mode;
7475 return (window_mode == this->windowMode());
7492 Xenium::WindowModeData& data = xenium->window_mode_map[window_id];
7494 if(data.window_mode == window_mode)
7496 return ZAKERO_XENIUM__ERROR(Error_None);
7499 std::error_code error = xenium->windowModeSet(window_id
7506 ZAKERO_XENIUM__DEBUG_ERROR(error);
7511 data.window_mode = window_mode;
7513 return ZAKERO_XENIUM__ERROR(Error_None);
7526 Xenium::WindowModeData& data = xenium->window_mode_map[window_id];
7528 if(lambda ==
nullptr)
7530 data.lambda = LambdaWindowMode_DoNothing;
7534 data.lambda = lambda;
7550 std::error_code error = xenium->windowMinimize(window_id);
7552 # if ZAKERO_XENIUM__DEBUG_ENABLED
7555 ZAKERO_XENIUM__DEBUG_ERROR(error);
7576 if(lambda ==
nullptr)
7578 xenium->window_keyboard[window_id].on_enter = Lambda_DoNothing;
7582 xenium->window_keyboard[window_id].on_enter = lambda;
7595 if(lambda ==
nullptr)
7597 xenium->window_keyboard[window_id].on_leave = Lambda_DoNothing;
7601 xenium->window_keyboard[window_id].on_leave = lambda;
7616 if(lambda ==
nullptr)
7618 xenium->window_on_key_map[window_id] = LambdaKey_DoNothing;
7622 xenium->window_on_key_map[window_id] = lambda;
7638 if(lambda ==
nullptr)
7640 xenium->window_on_axis_map[window_id] = LambdaAxis_DoNothing;
7644 xenium->window_on_axis_map[window_id] = lambda;
7659 WindowOnButtonData& on_button = xenium->window_on_button_map[window_id];
7661 if(lambda ==
nullptr)
7663 on_button.lambda_mm = LambdaButtonMm_DoNothing;
7667 on_button.lambda_mm = lambda;
7682 WindowOnButtonData& on_button = xenium->window_on_button_map[window_id];
7684 if(lambda ==
nullptr)
7686 on_button.lambda_percent = LambdaButtonPercent_DoNothing;
7690 on_button.lambda_percent = lambda;
7706 WindowOnButtonData& on_button = xenium->window_on_button_map[window_id];
7708 if(lambda ==
nullptr)
7710 on_button.lambda_pixel = LambdaButtonPixel_DoNothing;
7714 on_button.lambda_pixel = lambda;
7732 WindowOnEnterData& on_enter = xenium->window_on_enter_map[window_id];
7734 if(lambda ==
nullptr)
7736 on_enter.lambda_mm = LambdaPointMm_DoNothing;
7740 on_enter.lambda_mm = lambda;
7758 WindowOnEnterData& on_enter = xenium->window_on_enter_map[window_id];
7760 if(lambda ==
nullptr)
7762 on_enter.lambda_percent = LambdaPointPercent_DoNothing;
7766 on_enter.lambda_percent = lambda;
7784 WindowOnEnterData& on_enter = xenium->window_on_enter_map[window_id];
7786 if(lambda ==
nullptr)
7788 on_enter.lambda_pixel = LambdaPointPixel_DoNothing;
7792 on_enter.lambda_pixel = lambda;
7807 if(lambda ==
nullptr)
7809 xenium->window_on_leave_map[window_id] = Lambda_DoNothing;
7813 xenium->window_on_leave_map[window_id] = lambda;
7828 WindowOnMotionData& on_motion = xenium->window_on_motion_map[window_id];
7830 if(lambda ==
nullptr)
7832 on_motion.lambda_mm = LambdaPointMm_DoNothing;
7836 on_motion.lambda_mm = lambda;
7851 WindowOnMotionData& on_motion = xenium->window_on_motion_map[window_id];
7853 if(lambda ==
nullptr)
7855 on_motion.lambda_percent = LambdaPointPercent_DoNothing;
7859 on_motion.lambda_percent = lambda;
7874 WindowOnMotionData& on_motion = xenium->window_on_motion_map[window_id];
7876 if(lambda ==
nullptr)
7878 on_motion.lambda_pixel = LambdaPointPixel_DoNothing;
7882 on_motion.lambda_pixel = lambda;
7973 frame_buffer_size = xenium->window_size_map[window_id].pixel;
7974 frame_buffer_length = frame_buffer_size.width * frame_buffer_size.height * 4;
7975 frame_buffer = (uint8_t*)malloc(
sizeof(uint8_t) * frame_buffer_length);
7977 image = frame_buffer;
7978 size = frame_buffer_size;
7980 return ZAKERO_XENIUM__ERROR(Error_None);
8002 xcb_put_image(xenium->connection
8003 , XCB_IMAGE_FORMAT_Z_PIXMAP
8006 , frame_buffer_size.width
8007 , frame_buffer_size.height
8011 , xenium->screen->root_depth
8012 , frame_buffer_length
8058 std::string
to_string(
const xcb_generic_error_t& generic_error
8061 return std::string()
8062 +
"{ \"response_type\": " + std::to_string(generic_error.response_type)
8063 +
", \"error_code\": " + std::to_string(generic_error.error_code)
8064 +
", \"sequence\": " + std::to_string(generic_error.sequence)
8065 +
", \"resource_id\": " + std::to_string(generic_error.resource_id)
8066 +
", \"minor_code\": " + std::to_string(generic_error.minor_code)
8067 +
", \"major_code\": " + std::to_string(generic_error.major_code)
8068 +
", \"full_sequence\": " + std::to_string(generic_error.full_sequence)
8078 std::string
to_string(
const xcb_randr_screen_change_notify_event_t& event
8081 return std::string()
8082 +
"{ \"response_type\": " + std::to_string(event.response_type)
8083 +
", \"rotation\": " + std::to_string(event.rotation)
8084 +
", \"sequence\": " + std::to_string(event.sequence)
8085 +
", \"timestamp\": " + std::to_string(event.timestamp)
8086 +
", \"config_timestamp\": " + std::to_string(event.config_timestamp)
8087 +
", \"root\": " + std::to_string(event.root)
8088 +
", \"request_window\": " + std::to_string(event.request_window)
8089 +
", \"sizeID\": " + std::to_string(event.sizeID)
8090 +
", \"subpixel_order\": " + std::to_string(event.subpixel_order)
8091 +
", \"width\": " + std::to_string(event.width)
8092 +
", \"height\": " + std::to_string(event.height)
8093 +
", \"mwidth\": " + std::to_string(event.mwidth)
8094 +
", \"mheight\": " + std::to_string(event.mheight)
8106 return std::string()
8107 +
"{ \"response_type\": " + std::to_string(event.response_type)
8108 +
", \"detail\": " + std::to_string(event.detail)
8109 +
", \"sequence\": " + std::to_string(event.sequence)
8110 +
", \"time\": " + std::to_string(event.time)
8111 +
", \"root\": " + std::to_string(event.root)
8112 +
", \"event\": " + std::to_string(event.event)
8113 +
", \"child\": " + std::to_string(event.child)
8114 +
", \"root_x\": " + std::to_string(event.root_x)
8115 +
", \"root_y\": " + std::to_string(event.root_y)
8116 +
", \"event_x\": " + std::to_string(event.event_x)
8117 +
", \"event_y\": " + std::to_string(event.event_y)
8118 +
", \"state\": " + std::to_string(event.state)
8119 +
", \"same_screen\": " + std::to_string(event.same_screen)
8120 +
", \"pad0\": " + std::to_string(event.pad0)
8130 std::string
to_string(
const xcb_client_message_event_t& event
8133 return std::string()
8134 +
"{ \"response_type\": " + std::to_string(event.response_type)
8135 +
", \"format\": " + std::to_string(event.format)
8136 +
", \"sequence\": " + std::to_string(event.sequence)
8137 +
", \"window\": " + std::to_string(event.window)
8138 +
", \"type\": " + std::to_string(event.type)
8139 +
", \"data\": [ 0x" + std::to_string(event.data.data8[ 0])
8140 +
", 0x" + std::to_string(event.data.data8[ 1])
8141 +
", 0x" + std::to_string(event.data.data8[ 2])
8142 +
", 0x" + std::to_string(event.data.data8[ 3])
8143 +
", 0x" + std::to_string(event.data.data8[ 4])
8144 +
", 0x" + std::to_string(event.data.data8[ 5])
8145 +
", 0x" + std::to_string(event.data.data8[ 6])
8146 +
", 0x" + std::to_string(event.data.data8[ 7])
8147 +
", 0x" + std::to_string(event.data.data8[ 8])
8148 +
", 0x" + std::to_string(event.data.data8[ 9])
8149 +
", 0x" + std::to_string(event.data.data8[10])
8150 +
", 0x" + std::to_string(event.data.data8[11])
8151 +
", 0x" + std::to_string(event.data.data8[12])
8152 +
", 0x" + std::to_string(event.data.data8[13])
8153 +
", 0x" + std::to_string(event.data.data8[14])
8154 +
", 0x" + std::to_string(event.data.data8[15])
8155 +
", 0x" + std::to_string(event.data.data8[16])
8156 +
", 0x" + std::to_string(event.data.data8[17])
8157 +
", 0x" + std::to_string(event.data.data8[18])
8158 +
", 0x" + std::to_string(event.data.data8[19])
8169 std::string
to_string(
const xcb_configure_notify_event_t& event
8172 return std::string()
8173 +
"{ \"response_type\": " + std::to_string(event.response_type)
8174 +
", \"pad0\": " + std::to_string(event.pad0)
8175 +
", \"sequence\": " + std::to_string(event.sequence)
8176 +
", \"event\": " + std::to_string(event.event)
8177 +
", \"window\": " + std::to_string(event.window)
8178 +
", \"above_sibling\": " + std::to_string(event.above_sibling)
8179 +
", \"x\": " + std::to_string(event.x)
8180 +
", \"y\": " + std::to_string(event.y)
8181 +
", \"width\": " + std::to_string(event.width)
8182 +
", \"height\": " + std::to_string(event.height)
8183 +
", \"border_width\": " + std::to_string(event.border_width)
8184 +
", \"override_redirect\": " + std::to_string(event.override_redirect)
8185 +
", \"pad1\": " + std::to_string(event.pad1)
8198 return std::string()
8199 +
"{ \"response_type\": " + std::to_string(event.response_type)
8200 +
", \"detail\": " + std::to_string(event.detail)
8201 +
", \"sequence\": " + std::to_string(event.sequence)
8202 +
", \"time\": " + std::to_string(event.time)
8203 +
", \"root\": " + std::to_string(event.root)
8204 +
", \"event\": " + std::to_string(event.event)
8205 +
", \"root_x\": " + std::to_string(event.root_x)
8206 +
", \"root_y\": " + std::to_string(event.root_y)
8207 +
", \"event_x\": " + std::to_string(event.event_x)
8208 +
", \"event_y\": " + std::to_string(event.event_y)
8209 +
", \"state\": " + std::to_string(event.state)
8210 +
", \"mode\": " + std::to_string(event.mode)
8211 +
", \"same_screen_focus\": " + std::to_string(event.same_screen_focus)
8224 return std::string()
8225 +
"{ \"response_type\": " + std::to_string(event.response_type)
8226 +
", \"pad0\": " + std::to_string(event.pad0)
8227 +
", \"sequence\": " + std::to_string(event.sequence)
8228 +
", \"window\": " + std::to_string(event.window)
8229 +
", \"x\": " + std::to_string(event.x)
8230 +
", \"y\": " + std::to_string(event.y)
8231 +
", \"width\": " + std::to_string(event.width)
8232 +
", \"height\": " + std::to_string(event.height)
8233 +
", \"count\": " + std::to_string(event.count)
8234 +
", \"pad1\": [ 0x" + std::to_string(event.pad1[0])
8235 +
", 0x" + std::to_string(event.pad1[1])
8249 return std::string()
8250 +
"{ \"response_type\": " + std::to_string(event.response_type)
8251 +
", \"detail\": " + std::to_string(event.detail)
8252 +
", \"sequence\": " + std::to_string(event.sequence)
8253 +
", \"event\": " + std::to_string(event.event)
8254 +
", \"mode\": " + std::to_string(event.mode)
8255 +
", \"pad0\": [ 0x" + std::to_string(event.pad0[0])
8256 +
", 0x" + std::to_string(event.pad0[1])
8257 +
", 0x" + std::to_string(event.pad0[2])
8271 return std::string()
8272 +
"{ \"response_type\": " + std::to_string(event.response_type)
8273 +
", \"pad0\": " + std::to_string(event.pad0)
8274 +
", \"sequence\": " + std::to_string(event.sequence)
8275 +
", \"pad\": [ 0x" + std::to_string(event.pad[0])
8276 +
", 0x" + std::to_string(event.pad[1])
8277 +
", 0x" + std::to_string(event.pad[2])
8278 +
", 0x" + std::to_string(event.pad[3])
8279 +
", 0x" + std::to_string(event.pad[4])
8280 +
", 0x" + std::to_string(event.pad[5])
8281 +
", 0x" + std::to_string(event.pad[6])
8283 +
", \"full_sequence\": " + std::to_string(event.full_sequence)
8293 std::string
to_string(
const xcb_gravity_notify_event_t& event
8296 return std::string()
8297 +
"{ \"response_type\": " + std::to_string(event.response_type)
8298 +
", \"pad0\": " + std::to_string(event.pad0)
8299 +
", \"sequence\": " + std::to_string(event.sequence)
8300 +
", \"event\": " + std::to_string(event.event)
8301 +
", \"window\": " + std::to_string(event.window)
8302 +
", \"x\": " + std::to_string(event.x)
8303 +
", \"y\": " + std::to_string(event.y)
8316 return std::string()
8317 +
"{ \"response_type\": " + std::to_string(event.response_type)
8318 +
", \"detail\": " + std::to_string(event.detail)
8319 +
", \"sequence\": " + std::to_string(event.sequence)
8320 +
", \"time\": " + std::to_string(event.time)
8321 +
", \"root\": " + std::to_string(event.root)
8322 +
", \"event\": " + std::to_string(event.event)
8323 +
", \"child\": " + std::to_string(event.child)
8324 +
", \"root_x\": " + std::to_string(event.root_x)
8325 +
", \"root_y\": " + std::to_string(event.root_y)
8326 +
", \"event_x\": " + std::to_string(event.event_x)
8327 +
", \"event_y\": " + std::to_string(event.event_y)
8328 +
", \"state\": " + std::to_string(event.state)
8329 +
", \"same_screen\": " + std::to_string(event.same_screen)
8330 +
", \"pad0\": " + std::to_string(event.pad0)
8343 return std::string()
8344 +
"{ \"response_type\": " + std::to_string(event.response_type)
8345 +
", \"pad0\": " + std::to_string(event.pad0)
8346 +
", \"sequence\": " + std::to_string(event.sequence)
8347 +
", \"event\": " + std::to_string(event.event)
8348 +
", \"window\": " + std::to_string(event.window)
8349 +
", \"override_redirect\": " + std::to_string(event.override_redirect)
8350 +
", \"pad1\": [ 0x" + std::to_string(event.pad1[0])
8351 +
", 0x" + std::to_string(event.pad1[1])
8352 +
", 0x" + std::to_string(event.pad1[2])
8363 std::string
to_string(
const xcb_motion_notify_event_t& event
8366 return std::string()
8367 +
"{ \"response_type\": " + std::to_string(event.response_type)
8368 +
", \"detail\": " + std::to_string(event.detail)
8369 +
", \"sequence\": " + std::to_string(event.sequence)
8370 +
", \"time\": " + std::to_string(event.time)
8371 +
", \"root\": " + std::to_string(event.root)
8372 +
", \"event\": " + std::to_string(event.event)
8373 +
", \"child\": " + std::to_string(event.child)
8374 +
", \"root_x\": " + std::to_string(event.root_x)
8375 +
", \"root_y\": " + std::to_string(event.root_y)
8376 +
", \"event_x\": " + std::to_string(event.event_x)
8377 +
", \"event_y\": " + std::to_string(event.event_y)
8378 +
", \"state\": " + std::to_string(event.state)
8379 +
", \"same_screen\": " + std::to_string(event.same_screen)
8380 +
", \"pad0\": " + std::to_string(event.pad0)
8390 std::string
to_string(
const xcb_property_notify_event_t& event
8393 return std::string()
8394 +
"{ \"response_type\": " + std::to_string(event.response_type)
8395 +
", \"pad0\": " + std::to_string(event.pad0)
8396 +
", \"sequence\": " + std::to_string(event.sequence)
8397 +
", \"window\": " + std::to_string(event.window)
8398 +
", \"atom\": " + std::to_string(event.atom)
8399 +
", \"time\": " + std::to_string(event.time)
8400 +
", \"state\": " + std::to_string(event.state)
8401 +
", \"pad1\": [ 0x" + std::to_string(event.pad1[0])
8402 +
", 0x" + std::to_string(event.pad1[1])
8403 +
", 0x" + std::to_string(event.pad1[2])
8414 std::string
to_string(
const xcb_reparent_notify_event_t& event
8417 return std::string()
8418 +
"{ \"response_type\": " + std::to_string(event.response_type)
8419 +
", \"pad0\": " + std::to_string(event.pad0)
8420 +
", \"sequence\": " + std::to_string(event.sequence)
8421 +
", \"event\": " + std::to_string(event.event)
8422 +
", \"window\": " + std::to_string(event.window)
8423 +
", \"parent\": " + std::to_string(event.parent)
8424 +
", \"x\": " + std::to_string(event.x)
8425 +
", \"y\": " + std::to_string(event.y)
8426 +
", \"override_redirect\": " + std::to_string(event.override_redirect)
8427 +
", \"pad1\": [ 0x" + std::to_string(event.pad1[0])
8428 +
", 0x" + std::to_string(event.pad1[1])
8429 +
", 0x" + std::to_string(event.pad1[2])
8443 return std::string()
8444 +
"{ \"response_type\": " + std::to_string(event.response_type)
8445 +
", \"pad0\": " + std::to_string(event.pad0)
8446 +
", \"sequence\": " + std::to_string(event.sequence)
8447 +
", \"event\": " + std::to_string(event.event)
8448 +
", \"window\": " + std::to_string(event.window)
8449 +
", \"from_configure\": " + std::to_string(event.from_configure)
8450 +
", \"pad1\": [ 0x" + std::to_string(event.pad1[0])
8451 +
", 0x" + std::to_string(event.pad1[1])
8452 +
", 0x" + std::to_string(event.pad1[2])
8466 return std::string()
8467 +
"{ \"depth\": " + std::to_string(format.depth)
8468 +
", \"bits_per_pixel\": " + std::to_string(format.bits_per_pixel)
8469 +
", \"scanline_pad\": " + std::to_string(format.scanline_pad)
8470 +
", \"pad0\": [ 0x" + std::to_string(format.pad0[0])
8471 +
", 0x" + std::to_string(format.pad0[1])
8472 +
", 0x" + std::to_string(format.pad0[2])
8473 +
", 0x" + std::to_string(format.pad0[3])
8474 +
", 0x" + std::to_string(format.pad0[4])
8488 return std::string()
8489 +
"{ \"root\": " + std::to_string(screen.root)
8490 +
", \"default_colormap\": " + std::to_string(screen.default_colormap)
8491 +
", \"white_pixel\": " + std::to_string(screen.white_pixel)
8492 +
", \"black_pixel\": " + std::to_string(screen.black_pixel)
8493 +
", \"current_input_masks\": " + std::to_string(screen.current_input_masks)
8494 +
", \"width_in_pixels\": " + std::to_string(screen.width_in_pixels)
8495 +
", \"height_in_pixels\": " + std::to_string(screen.height_in_pixels)
8496 +
", \"width_in_millimeters\": " + std::to_string(screen.width_in_millimeters)
8497 +
", \"height_in_millimeters\": " + std::to_string(screen.height_in_millimeters)
8498 +
", \"min_installed_maps\": " + std::to_string(screen.min_installed_maps)
8499 +
", \"max_installed_maps\": " + std::to_string(screen.max_installed_maps)
8500 +
", \"root_visual\": " + std::to_string(screen.root_visual)
8501 +
", \"backing_stores\": " + std::to_string(screen.backing_stores)
8502 +
", \"save_unders\": " + std::to_string(screen.save_unders)
8503 +
", \"root_depth\": " + std::to_string(screen.root_depth)
8504 +
", \"allowed_depths_len\": " + std::to_string(screen.allowed_depths_len)
8517 std::string
string =
"[ ";
8518 std::string delim =
"";
8520 for(
const auto& atom : vector)
8522 string += delim +
' ' + std::to_string(atom);
8541 std::string
string =
"[ ";
8542 std::string delim =
"";
8544 for(
const int32_t& value : vector)
8546 string += delim +
' ' + std::to_string(value);
8565 return std::string()
8566 +
"{ \"status\": " + std::to_string(setup.status)
8567 +
", \"pad0\": " + std::to_string(setup.pad0)
8568 +
", \"protocol_major_version\": " + std::to_string(setup.protocol_major_version)
8569 +
", \"protocol_minor_version\": " + std::to_string(setup.protocol_minor_version)
8570 +
", \"length\": " + std::to_string(setup.length)
8571 +
", \"release_number\": " + std::to_string(setup.release_number)
8572 +
", \"resource_id_base\": " + std::to_string(setup.resource_id_base)
8573 +
", \"resource_id_mask\": " + std::to_string(setup.resource_id_mask)
8574 +
", \"motion_buffer_size\": " + std::to_string(setup.motion_buffer_size)
8575 +
", \"vendor_len\": " + std::to_string(setup.vendor_len)
8576 +
", \"maximum_request_length\": " + std::to_string(setup.maximum_request_length)
8577 +
", \"roots_len\": " + std::to_string(setup.roots_len)
8578 +
", \"pixmap_formats_len\": " + std::to_string(setup.pixmap_formats_len)
8579 +
", \"image_byte_order\": " + std::to_string(setup.image_byte_order)
8580 +
", \"bitmap_format_bit_order\": " + std::to_string(setup.bitmap_format_bit_order)
8581 +
", \"bitmap_format_scanline_unit\": " + std::to_string(setup.bitmap_format_scanline_unit)
8582 +
", \"bitmap_format_scanline_pad\": " + std::to_string(setup.bitmap_format_scanline_pad)
8583 +
", \"min_keycode\": " + std::to_string(setup.min_keycode)
8584 +
", \"max_keycode\": " + std::to_string(setup.max_keycode)
8585 +
", \"pad1\": [ 0x" + std::to_string(setup.pad1[0])
8586 +
", 0x" + std::to_string(setup.pad1[1])
8587 +
", 0x" + std::to_string(setup.pad1[2])
8588 +
", 0x" + std::to_string(setup.pad1[3])
8604 return std::string()
8605 +
"{ \"time\": " + std::to_string(key.time)
8606 +
", \"code\": " + std::to_string(key.code)
8624 auto mod_to_str = [](std::string& s, uint32_t m)
8627 std::string delim =
"";
8631 s += delim +
"\"Shift\"";
8637 s += delim +
"\"CapsLock\"";
8643 s += delim +
"\"Control\"";
8649 s += delim +
"\"Alt\"";
8655 s += delim +
"\"Meta\"";
8660 s += delim +
"\"NumLock\"";
8666 std::string str =
"{ \"pressed\": ";
8667 mod_to_str(str, key_modifier.pressed);
8669 str +=
", \"latched\": ";
8670 mod_to_str(str, key_modifier.latched);
8672 str +=
", \"locked\": ";
8673 mod_to_str(str, key_modifier.locked);
8693 case Xenium::KeyState::Pressed:
return "Pressed";
8694 case Xenium::KeyState::Released:
return "Released";
8695 case Xenium::KeyState::Repeat:
return "Repeat";
8711 return std::string()
8713 +
", \"x\": " + std::to_string(
output.
x)
8714 +
", \"y\": " + std::to_string(
output.
y)
8741 return std::string()
8742 +
"{ \"time\": " + std::to_string(point.time)
8743 +
", \"x\": " + std::to_string(point.x)
8744 +
", \"y\": " + std::to_string(point.y)
8760 return std::string()
8761 +
"{ \"time\": " + std::to_string(point.time)
8762 +
", \"x\": " + std::to_string(point.x)
8763 +
", \"y\": " + std::to_string(point.y)
8779 return std::string()
8780 +
"{ \"time\": " + std::to_string(point.time)
8781 +
", \"x\": " + std::to_string(point.x)
8782 +
", \"y\": " + std::to_string(point.y)
8798 return std::string()
8799 +
"{ \"time\": " + std::to_string(pointer_axis.time)
8800 +
", \"steps\": " + std::to_string(pointer_axis.steps)
8801 +
", \"distance\": " + std::to_string(pointer_axis.distance)
8821 case Xenium::PointerAxisSource::Continuous:
return "Continuous";
8822 case Xenium::PointerAxisSource::Finger:
return "Finger";
8823 case Xenium::PointerAxisSource::Wheel:
return "Wheel";
8824 case Xenium::PointerAxisSource::Wheel_Tilt:
return "Wheel Tilt";
8825 case Xenium::PointerAxisSource::Unknown: [[fallthrough]];
8843 case Xenium::PointerAxisType::Horizontal:
return "Horizontal";
8844 case Xenium::PointerAxisType::Vertical:
return "Vertical";
8845 case Xenium::PointerAxisType::Unknown: [[fallthrough]];
8861 std::string str = std::string()
8862 +
"{ \"code\": " + std::to_string(button.code)
8881 switch(button_state)
8883 case Xenium::PointerButtonState::Pressed:
return "Pressed";
8884 case Xenium::PointerButtonState::Released:
return "Released";
8900 return std::string()
8901 +
"{ \"width\": " + std::to_string(size.width)
8902 +
", \"height\": " + std::to_string(size.height)
8917 return std::string()
8918 +
"{ \"width\": " + std::to_string(size.width)
8919 +
", \"height\": " + std::to_string(size.height)
8934 return std::string()
8935 +
"{ \"width\": " + std::to_string(size.width)
8936 +
", \"height\": " + std::to_string(size.height)
8951 switch(window_decorations)
8953 case Xenium::WindowDecorations::Client_Side:
return "Client Side";
8954 case Xenium::WindowDecorations::Server_Side:
return "Server Side";
8972 case Xenium::WindowMode::Fullscreen:
return "Fullscreen";
8973 case Xenium::WindowMode::Maximized:
return "Maximized";
8974 case Xenium::WindowMode::Normal:
return "Normal";
9040 return (lhs.x == rhs.x) && (lhs.y == rhs.y);
9098 return (lhs.width == rhs.width) && (lhs.height == rhs.height);
std::string to_string(const bool value) noexcept
Convert a bool into a string.
Definition: Zakero_Base.h:534
#define ZAKERO_STEADY_TIME_NOW(unit_)
Get the current time.
Definition: Zakero_Base.h:205
#define ZAKERO_FREE(ptr_)
Free memory.
Definition: Zakero_Base.h:138
bool equalish(const float a, const float b, const float delta) noexcept
Compare two floats.
Definition: Zakero_Base.h:348
bool operator==(Xenium::PointMm &lhs, Xenium::PointMm &rhs) noexcept
Compare two Point objects.
Definition: Zakero_Xenium.h:8993
#define _NET_WM_STATE_REMOVE
A NET-WM Macro (that may not be defined).
Definition: Zakero_Xenium.h:1066
#define _NET_WM_STATE_ADD
A NET-WM Macro (that may not be defined).
Definition: Zakero_Xenium.h:1073
A Window.
Definition: Zakero_Xenium.h:501
void keyboardOnKey(Xenium::LambdaKey) noexcept
Respond to "Keyboard Key" events.
Definition: Zakero_Xenium.h:7613
void decorationsOnChange(Xenium::LambdaWindowDecorations) noexcept
Respond to "Decoration Change" events.
Definition: Zakero_Xenium.h:6865
void pointerOnEnter(Xenium::LambdaPointMm) noexcept
Respond to "Pointer Enter" events.
Definition: Zakero_Xenium.h:7729
void titleSet(const std::string &) noexcept
Change the window title.
Definition: Zakero_Xenium.h:6739
void pointerOnAxis(Xenium::LambdaAxis) noexcept
Respond to "Pointer Axis" events.
Definition: Zakero_Xenium.h:7635
std::error_code sizeSetMinMax(const Xenium::SizeMm &, const Xenium::SizeMm &) noexcept
Set the minimum window size.
Definition: Zakero_Xenium.h:7065
void sizeOnChange(Xenium::LambdaSizeMm) noexcept
Respond to "Resize" events.
Definition: Zakero_Xenium.h:7211
std::error_code sizeSet(const Xenium::SizeMm &) noexcept
Set the window size.
Definition: Zakero_Xenium.h:6900
void onCloseRequest(Xenium::Lambda) noexcept
Respond to "Close Request" events.
Definition: Zakero_Xenium.h:6771
virtual ~Window()
Destroy a Window.
Definition: Zakero_Xenium.h:6675
Xenium::PointPercent convertToPercent(const Xenium::PointPixel &) const noexcept
Unit conversion.
Definition: Zakero_Xenium.h:7314
void pointerOnButton(Xenium::LambdaButtonMm) noexcept
Respond to "Pointer Button" events.
Definition: Zakero_Xenium.h:7656
uint8_t bytesPerPixel() const noexcept
Get the number of bytes per pixel.
Definition: Zakero_Xenium.h:8045
void keyboardOnLeave(Xenium::Lambda) noexcept
Respond to "Keyboard Leave" events.
Definition: Zakero_Xenium.h:7592
bool windowModeIs(const Xenium::WindowMode) const noexcept
Check the WindowMode.
Definition: Zakero_Xenium.h:7472
std::error_code minimize() noexcept
Minimize the window.
Definition: Zakero_Xenium.h:7548
std::error_code decorationsSet(const Xenium::WindowDecorations) noexcept
Use the Desktop Environment borders.
Definition: Zakero_Xenium.h:6831
Window(Xenium *, void *)
Construct a Window.
Definition: Zakero_Xenium.h:6658
Xenium::PointPixel convertToPixel(const Xenium::PointMm &) const noexcept
Unit conversion.
Definition: Zakero_Xenium.h:7334
void pointerOnMotion(Xenium::LambdaPointMm) noexcept
Respond to "Pointer Motion" events.
Definition: Zakero_Xenium.h:7825
uint32_t time() const noexcept
When the last frame was rendered.
Definition: Zakero_Xenium.h:8031
void keyboardOnEnter(Xenium::Lambda) noexcept
Respond to "Keyboard Enter" events.
Definition: Zakero_Xenium.h:7573
void imagePresent() noexcept
Render the image.
Definition: Zakero_Xenium.h:7990
Xenium::WindowMode windowMode() const noexcept
Get the current WindowMode.
Definition: Zakero_Xenium.h:7457
std::error_code imageNext(uint8_t *&, Xenium::SizePixel &) noexcept
Get an image buffer.
Definition: Zakero_Xenium.h:7964
Xenium::PointMm convertToMm(const Xenium::PointPixel &) const noexcept
Unit conversion.
Definition: Zakero_Xenium.h:7294
std::error_code windowModeSet(const Xenium::WindowMode) noexcept
Change the window mode.
Definition: Zakero_Xenium.h:7489
void pointerOnLeave(Xenium::Lambda) noexcept
Respond to "Pointer Leave" events.
Definition: Zakero_Xenium.h:7804
void onFocusChange(Xenium::LambdaBool) noexcept
Respond to "Active" change events.
Definition: Zakero_Xenium.h:6800
void classSet(const std::string &) noexcept
Change the window class.
Definition: Zakero_Xenium.h:6714
void windowModeOnChange(Xenium::LambdaWindowMode) noexcept
Respond to "Window Mode" events.
Definition: Zakero_Xenium.h:7523
A wrapper class for X11/XCB.
Definition: Zakero_Xenium.h:258
static constexpr uint32_t KeyModifier_Shift
Key Modifier flag.
Definition: Zakero_Xenium.h:284
uint32_t locked
A collection of locked modifiers.
Definition: Zakero_Xenium.h:295
uint32_t physical_height_mm
The height of the device in millimeters.
Definition: Zakero_Xenium.h:424
Xenium::Output output(const Xenium::OutputId) const noexcept
Get a copy of the Output information.
Definition: Zakero_Xenium.h:2898
uint32_t latched
A collection of latched modifiers.
Definition: Zakero_Xenium.h:294
int32_t x
The X position within the global compositor.
Definition: Zakero_Xenium.h:419
int32_t steps
The number of rotation steps.
Definition: Zakero_Xenium.h:349
int32_t keyRepeatRate() const noexcept
The key repeat rate.
Definition: Zakero_Xenium.h:2878
void outputOnRemove(Xenium::LambdaOutputId) noexcept
Notification of removing an Output device.
Definition: Zakero_Xenium.h:3251
Xenium::PointMm outputConvertToMm(const Xenium::OutputId, const Xenium::PointPixel &) const noexcept
Convert Pixel to Millimeter.
Definition: Zakero_Xenium.h:2996
std::function< void(Xenium::WindowMode)> LambdaWindowMode
A Lambda that has a parameter: WindowMode.
Definition: Zakero_Xenium.h:494
static std::string outputSubpixelName(int32_t) noexcept
Get a human readable string.
Definition: Zakero_Xenium.h:2951
Xenium::PointerAxisType type
The type of Axis.
Definition: Zakero_Xenium.h:352
std::function< void(const Xenium::PointerButton &, const Xenium::PointMm &, const Xenium::KeyModifier &)> LambdaButtonMm
A Lambda that has parameters: PointerButton, PointMm and KeyModifier.
Definition: Zakero_Xenium.h:483
int32_t y
The Y position within the global compositor.
Definition: Zakero_Xenium.h:420
std::function< void(const Xenium::SizePercent &)> LambdaSizePercent
A Lambda that has a parameter: SizePercent.
Definition: Zakero_Xenium.h:491
static constexpr uint32_t KeyModifier_Control
Key Modifier flag.
Definition: Zakero_Xenium.h:286
float distance
The distance traveled.
Definition: Zakero_Xenium.h:350
PointerButtonState
Mouse button state.
Definition: Zakero_Xenium.h:359
std::function< void(const Xenium::PointerButton &, const Xenium::PointPercent &, const Xenium::KeyModifier &)> LambdaButtonPercent
A Lambda that has parameters: PointerButton, PointPercent and KeyModifier.
Definition: Zakero_Xenium.h:484
WindowMode
All the available window modes.
Definition: Zakero_Xenium.h:473
uint32_t physical_width_mm
The width of the device in millimeters.
Definition: Zakero_Xenium.h:423
PointerAxisSource
Where the axis information came from.
Definition: Zakero_Xenium.h:333
std::function< void(const Xenium::PointPercent &, const Xenium::KeyModifier &)> LambdaPointPercent
A Lambda that has parameters: PointPercent and KeyModifier.
Definition: Zakero_Xenium.h:488
float pixels_per_mm_horizontal
A pre-calculated value.
Definition: Zakero_Xenium.h:427
std::function< void(const Xenium::SizeMm &)> LambdaSizeMm
A Lambda that has a parameter: SizeMm.
Definition: Zakero_Xenium.h:490
int32_t height
The height of the device in hardware units.
Definition: Zakero_Xenium.h:422
std::function< void(const Xenium::PointerButton &, const Xenium::PointPixel &, const Xenium::KeyModifier &)> LambdaButtonPixel
A Lambda that has parameters: PointerButton, PointPixel and KeyModifier.
Definition: Zakero_Xenium.h:485
Xenium::VectorOutputId outputVector() const noexcept
Get a list of the Output Id's.
Definition: Zakero_Xenium.h:2926
std::string name
The name of the output.
Definition: Zakero_Xenium.h:418
std::function< void(const Xenium::Key &, const Xenium::KeyModifier &)> LambdaKey
A Lambda that has parameters: Key and KeyModifier.
Definition: Zakero_Xenium.h:486
std::function< void()> Lambda
A Lambda that has no parameters.
Definition: Zakero_Xenium.h:480
Xenium::PointerButtonState state
The button state.
Definition: Zakero_Xenium.h:366
std::function< void(bool)> LambdaBool
A Lambda that has a parameter: bool.
Definition: Zakero_Xenium.h:482
uint32_t WindowId
A type for better readablity.
Definition: Zakero_Xenium.h:496
Xenium::PointPixel outputConvertToPixel(const Xenium::OutputId, const Xenium::PointMm &) const noexcept
Convert Millimeter to Pixel.
Definition: Zakero_Xenium.h:3050
int32_t transform
Transform that maps framebuffer to output.
Definition: Zakero_Xenium.h:426
Xenium::Window * windowCreate(const Xenium::SizeMm &, std::error_code &) noexcept
Create a window.
Definition: Zakero_Xenium.h:3701
KeyState
Keyboard key state
Definition: Zakero_Xenium.h:272
static constexpr uint32_t KeyModifier_Meta
Key Modifier flag.
Definition: Zakero_Xenium.h:289
WindowDecorations
Who is responsible for rendering the decorations.
Definition: Zakero_Xenium.h:468
void outputOnChange(Xenium::LambdaOutputId) noexcept
Notification that an Output device has changed.
Definition: Zakero_Xenium.h:3230
static Xenium * connect() noexcept
Establish a connection with the X11 server.
Definition: Zakero_Xenium.h:2390
virtual ~Xenium() noexcept
Destructor.
Definition: Zakero_Xenium.h:2357
std::function< void(Xenium::WindowDecorations)> LambdaWindowDecorations
A Lambda that has a parameter: WindowDecorations.
Definition: Zakero_Xenium.h:493
int32_t subpixel
The device's subpixel orientation.
Definition: Zakero_Xenium.h:425
uint32_t pressed
A collection of pressed modifiers.
Definition: Zakero_Xenium.h:293
int32_t keyRepeatDelay() const noexcept
The key repeat delay.
Definition: Zakero_Xenium.h:2865
int32_t width
The width of the device in hardware units.
Definition: Zakero_Xenium.h:421
uint32_t code
The key code of the event.
Definition: Zakero_Xenium.h:280
std::function< void(const Xenium::PointPixel &, const Xenium::KeyModifier &)> LambdaPointPixel
A Lambda that has parameters: PointPixel and KeyModifier.
Definition: Zakero_Xenium.h:489
static constexpr uint32_t KeyModifier_Alt
Key Modifier flag.
Definition: Zakero_Xenium.h:287
std::function< void(const Xenium::SizePixel &)> LambdaSizePixel
A Lambda that has a parameter: SizePixel.
Definition: Zakero_Xenium.h:492
Xenium::KeyState state
The state of the key.
Definition: Zakero_Xenium.h:281
Xenium::PointPercent outputConvertToPercent(const Xenium::OutputId, const Xenium::PointPixel &) const noexcept
Convert Pixel to a Percentage.
Definition: Zakero_Xenium.h:3023
void outputOnAdd(Xenium::LambdaOutputId) noexcept
Notification of adding an Output device.
Definition: Zakero_Xenium.h:3209
uint32_t time
When the event occurred.
Definition: Zakero_Xenium.h:348
std::function< void(const Xenium::PointerAxis &, const Xenium::KeyModifier &)> LambdaAxis
A Lambda that has parameters: PointerAxis and KeyModifier.
Definition: Zakero_Xenium.h:481
static constexpr uint32_t KeyModifier_CapsLock
Key Modifier flag.
Definition: Zakero_Xenium.h:285
std::function< void(const Xenium::PointMm &, const Xenium::KeyModifier &)> LambdaPointMm
A Lambda that has parameters: PointMm and KeyModifier.
Definition: Zakero_Xenium.h:487
uint32_t code
The event code.
Definition: Zakero_Xenium.h:365
uint32_t time
When the key event happened.
Definition: Zakero_Xenium.h:279
static constexpr uint32_t KeyModifier_NumLock
Key Modifier flag.
Definition: Zakero_Xenium.h:288
Xenium::PointerAxisSource source
The source of the event.
Definition: Zakero_Xenium.h:351
uint32_t group
The keyboard layout.
Definition: Zakero_Xenium.h:296
float pixels_per_mm_vertical
A pre-calculated value.
Definition: Zakero_Xenium.h:428
PointerAxisType
The direction of the axis movement.
Definition: Zakero_Xenium.h:341
static std::string outputTransformName(int32_t) noexcept
Get a human readable string.
Definition: Zakero_Xenium.h:2974
Key event information.
Definition: Zakero_Xenium.h:278
A collection modifier flags.
Definition: Zakero_Xenium.h:292
Information about a output device.
Definition: Zakero_Xenium.h:417
Information about an Axis event.
Definition: Zakero_Xenium.h:347
A location that uses millimeters.
Definition: Zakero_Xenium.h:303
float y
Where in the Y-Axis the point is.
Definition: Zakero_Xenium.h:306
float x
Where in the X-Axis the point is.
Definition: Zakero_Xenium.h:305
uint32_t time
Where in time the point is (if > 0).
Definition: Zakero_Xenium.h:304
friend bool operator==(Xenium::PointMm &, Xenium::PointMm &) noexcept
Compare two Point objects.
Definition: Zakero_Xenium.h:8993
A location that uses percentages.
Definition: Zakero_Xenium.h:312
float x
Where in the X-Axis the point is.
Definition: Zakero_Xenium.h:314
uint32_t time
Where in time the point is (if > 0).
Definition: Zakero_Xenium.h:313
float y
Where in the Y-Axis the point is.
Definition: Zakero_Xenium.h:315
friend bool operator==(Xenium::PointPercent &, Xenium::PointPercent &) noexcept
Compare two Point objects.
Definition: Zakero_Xenium.h:9016
A location that uses pixels.
Definition: Zakero_Xenium.h:321
friend bool operator==(Xenium::PointPixel &, Xenium::PointPixel &) noexcept
Compare two Point objects.
Definition: Zakero_Xenium.h:9036
uint32_t time
Where in time the point is (if > 0).
Definition: Zakero_Xenium.h:322
int32_t y
Where in the Y-Axis the point is.
Definition: Zakero_Xenium.h:324
int32_t x
Where in the X-Axis the point is.
Definition: Zakero_Xenium.h:323
Size measured in millimeters.
Definition: Zakero_Xenium.h:373
friend bool operator==(Xenium::SizeMm &, Xenium::SizeMm &) noexcept
Compare two Point objects.
Definition: Zakero_Xenium.h:9055
Size measured as a percentage of the Output (Monitor) resolution.
Definition: Zakero_Xenium.h:381
friend bool operator==(Xenium::SizePercent &, Xenium::SizePercent &) noexcept
Compare two Point objects.
Definition: Zakero_Xenium.h:9076
Size measured in pixels.
Definition: Zakero_Xenium.h:389
friend bool operator==(Xenium::SizePixel &, Xenium::SizePixel &) noexcept
Compare two Size objects.
Definition: Zakero_Xenium.h:9094