Compare commits
9 Commits
16d57d0194
...
aa70815f5f
| Author | SHA1 | Date | |
|---|---|---|---|
| aa70815f5f | |||
| 19f043744a | |||
| af2132315d | |||
| 83af554e8c | |||
| b41d979dcb | |||
| 11ebced96a | |||
| 504eb2716b | |||
| 82edc9c76b | |||
| 92e02dcadf |
194
xbanan/Base.cpp
194
xbanan/Base.cpp
@@ -28,6 +28,8 @@ CARD16 g_keymask { 0 };
|
|||||||
CARD16 g_butmask { 0 };
|
CARD16 g_butmask { 0 };
|
||||||
WINDOW g_focus_window { None };
|
WINDOW g_focus_window { None };
|
||||||
|
|
||||||
|
static WINDOW s_pointer_grab_wid = None;
|
||||||
|
|
||||||
static const char* s_opcode_to_name[] {
|
static const char* s_opcode_to_name[] {
|
||||||
[0] = "none",
|
[0] = "none",
|
||||||
[X_CreateWindow] = "X_CreateWindow",
|
[X_CreateWindow] = "X_CreateWindow",
|
||||||
@@ -374,6 +376,9 @@ void invalidate_window(WINDOW wid, int32_t x, int32_t y, int32_t w, int32_t h)
|
|||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
if (wid == g_root.windowId)
|
||||||
|
return;
|
||||||
|
|
||||||
auto& object = *g_objects[wid];
|
auto& object = *g_objects[wid];
|
||||||
ASSERT(object.type == Object::Type::Window);
|
ASSERT(object.type == Object::Type::Window);
|
||||||
|
|
||||||
@@ -447,7 +452,7 @@ void send_exposure_recursive(WINDOW wid)
|
|||||||
|
|
||||||
struct PlatformWindowInfo
|
struct PlatformWindowInfo
|
||||||
{
|
{
|
||||||
PlatformWindow* transient_for;
|
PlatformWindow* parent;
|
||||||
WindowType type;
|
WindowType type;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -463,7 +468,7 @@ static PlatformWindowInfo get_plaform_window_info(const Object::Window& window)
|
|||||||
static const CARD32 _NET_WM_WINDOW_TYPE_UTILITY = g_atoms_name_to_id["_NET_WM_WINDOW_TYPE_UTILITY"_sv];
|
static const CARD32 _NET_WM_WINDOW_TYPE_UTILITY = g_atoms_name_to_id["_NET_WM_WINDOW_TYPE_UTILITY"_sv];
|
||||||
|
|
||||||
PlatformWindowInfo info {
|
PlatformWindowInfo info {
|
||||||
.transient_for = nullptr,
|
.parent = nullptr,
|
||||||
.type = WindowType::Normal,
|
.type = WindowType::Normal,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -475,7 +480,7 @@ static PlatformWindowInfo get_plaform_window_info(const Object::Window& window)
|
|||||||
const CARD32 type = *reinterpret_cast<const CARD32*>(it->value.data.data());
|
const CARD32 type = *reinterpret_cast<const CARD32*>(it->value.data.data());
|
||||||
if (type == _NET_WM_WINDOW_TYPE_NORMAL)
|
if (type == _NET_WM_WINDOW_TYPE_NORMAL)
|
||||||
info.type = WindowType::Normal;
|
info.type = WindowType::Normal;
|
||||||
else if (type == _NET_WM_WINDOW_TYPE_SPLASH || type == _NET_WM_WINDOW_TYPE_UTILITY || type == _NET_WM_WINDOW_TYPE_DIALOG)
|
else if (type == _NET_WM_WINDOW_TYPE_SPLASH || type == _NET_WM_WINDOW_TYPE_DIALOG)
|
||||||
info.type = WindowType::Utility;
|
info.type = WindowType::Utility;
|
||||||
else
|
else
|
||||||
info.type = WindowType::Popup;
|
info.type = WindowType::Popup;
|
||||||
@@ -497,7 +502,7 @@ wm_window_type_done:
|
|||||||
|
|
||||||
// FIXME: support child windows
|
// FIXME: support child windows
|
||||||
auto& window = it2->value->object.get<Object::Window>();
|
auto& window = it2->value->object.get<Object::Window>();
|
||||||
info.transient_for = window.platform_window.ptr();
|
info.parent = window.platform_window.ptr();
|
||||||
}
|
}
|
||||||
transitient_for_done:
|
transitient_for_done:
|
||||||
|
|
||||||
@@ -512,14 +517,21 @@ static BAN::ErrorOr<void> map_window(Client& client_info, WINDOW wid)
|
|||||||
auto& window = object.object.get<Object::Window>();
|
auto& window = object.object.get<Object::Window>();
|
||||||
if (window.mapped)
|
if (window.mapped)
|
||||||
return {};
|
return {};
|
||||||
|
window.mapped = true;
|
||||||
|
|
||||||
if (window.parent == g_root.windowId)
|
if (window.parent == g_root.windowId)
|
||||||
{
|
{
|
||||||
ASSERT(!window.platform_window);
|
ASSERT(!window.platform_window);
|
||||||
|
|
||||||
|
// NOTE: This is not perfect but seems to work.
|
||||||
|
// This is used to not display "dummy" event windows
|
||||||
|
// that should not be visible.
|
||||||
|
if (window.width <= 10 || window.height <= 10)
|
||||||
|
return {};
|
||||||
|
|
||||||
auto info = get_plaform_window_info(window);
|
auto info = get_plaform_window_info(window);
|
||||||
window.platform_window = TRY(g_platform_ops.create_window(
|
window.platform_window = TRY(g_platform_ops.create_window(
|
||||||
info.transient_for,
|
info.parent,
|
||||||
info.type,
|
info.type,
|
||||||
wid,
|
wid,
|
||||||
window.x,
|
window.x,
|
||||||
@@ -529,8 +541,6 @@ static BAN::ErrorOr<void> map_window(Client& client_info, WINDOW wid)
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
window.mapped = true;
|
|
||||||
|
|
||||||
for (auto& pixel : window.pixels)
|
for (auto& pixel : window.pixels)
|
||||||
pixel = window.background;
|
pixel = window.background;
|
||||||
invalidate_window(wid, 0, 0, window.width, window.height);
|
invalidate_window(wid, 0, 0, window.width, window.height);
|
||||||
@@ -711,6 +721,21 @@ WINDOW find_child_window(WINDOW wid, int32_t& x, int32_t& y)
|
|||||||
return wid;
|
return wid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xPoint get_window_position(WINDOW wid)
|
||||||
|
{
|
||||||
|
xPoint result { .x = 0, .y = 0 };
|
||||||
|
|
||||||
|
while (wid != None)
|
||||||
|
{
|
||||||
|
const auto& window = g_objects[wid]->object.get<Object::Window>();
|
||||||
|
result.x += window.x;
|
||||||
|
result.y += window.y;
|
||||||
|
wid = window.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static PlatformWindow* get_platform_window(const Object::Window& window)
|
static PlatformWindow* get_platform_window(const Object::Window& window)
|
||||||
{
|
{
|
||||||
if (window.platform_window)
|
if (window.platform_window)
|
||||||
@@ -1231,18 +1256,21 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool window_changed = false;
|
bool send_configure = false;
|
||||||
|
|
||||||
const int32_t min_x = BAN::Math::min(window.x, new_x);
|
|
||||||
const int32_t min_y = BAN::Math::min(window.y, new_y);
|
|
||||||
const int32_t max_x = BAN::Math::max(window.x + window.width, new_x + new_width);
|
|
||||||
const int32_t max_y = BAN::Math::max(window.y + window.height, new_y + new_height);
|
|
||||||
|
|
||||||
if (new_x != window.x || new_y != window.y)
|
if (new_x != window.x || new_y != window.y)
|
||||||
{
|
{
|
||||||
window.x = new_x;
|
if (window.platform_window)
|
||||||
window.y = new_y;
|
{
|
||||||
window_changed = true;
|
if (g_platform_ops.request_reposition)
|
||||||
|
g_platform_ops.request_reposition(window.platform_window.ptr(), new_x, new_y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
window.x = new_x;
|
||||||
|
window.y = new_y;
|
||||||
|
send_configure = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_width != window.width || new_height != window.height)
|
if (new_width != window.width || new_height != window.height)
|
||||||
@@ -1251,22 +1279,20 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
|||||||
{
|
{
|
||||||
if (g_platform_ops.request_resize)
|
if (g_platform_ops.request_resize)
|
||||||
g_platform_ops.request_resize(window.platform_window.ptr(), new_width, new_height);
|
g_platform_ops.request_resize(window.platform_window.ptr(), new_width, new_height);
|
||||||
window_changed = false;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
window.width = new_width;
|
|
||||||
window.height = new_height;
|
|
||||||
|
|
||||||
TRY(window.pixels.resize(new_width * new_height));
|
TRY(window.pixels.resize(new_width * new_height));
|
||||||
for (auto& pixel : window.pixels)
|
for (auto& pixel : window.pixels)
|
||||||
pixel = window.background;
|
pixel = window.background;
|
||||||
|
|
||||||
window_changed = true;
|
window.width = new_width;
|
||||||
|
window.height = new_height;
|
||||||
|
send_configure = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!window_changed)
|
if (!send_configure)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -1828,13 +1854,37 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
|||||||
dprintln(" cursor: {}", request.cursor);
|
dprintln(" cursor: {}", request.cursor);
|
||||||
dprintln(" time: {}", request.time);
|
dprintln(" time: {}", request.time);
|
||||||
|
|
||||||
xGrabPointerReply reply {
|
auto& window = TRY_REF(get_window(client_info, request.grabWindow, X_GrabPointer));
|
||||||
.type = X_Reply,
|
|
||||||
.status = Success,
|
if (s_pointer_grab_wid != None && !g_objects.contains(s_pointer_grab_wid))
|
||||||
.sequenceNumber = client_info.sequence,
|
s_pointer_grab_wid = None;
|
||||||
.length = 0,
|
|
||||||
};
|
if (s_pointer_grab_wid == None)
|
||||||
TRY(encode(client_info.output_buffer, reply));
|
{
|
||||||
|
xGrabPointerReply reply {
|
||||||
|
.type = X_Reply,
|
||||||
|
.status = Success,
|
||||||
|
.sequenceNumber = client_info.sequence,
|
||||||
|
.length = 0,
|
||||||
|
};
|
||||||
|
TRY(encode(client_info.output_buffer, reply));
|
||||||
|
|
||||||
|
if (g_platform_ops.set_pointer_grab)
|
||||||
|
if (auto* platform_window = get_platform_window(window))
|
||||||
|
g_platform_ops.set_pointer_grab(platform_window, true);
|
||||||
|
|
||||||
|
s_pointer_grab_wid = request.grabWindow;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xGrabPointerReply reply {
|
||||||
|
.type = X_Reply,
|
||||||
|
.status = AlreadyGrabbed,
|
||||||
|
.sequenceNumber = client_info.sequence,
|
||||||
|
.length = 0,
|
||||||
|
};
|
||||||
|
TRY(encode(client_info.output_buffer, reply));
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1845,6 +1895,16 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
|||||||
dprintln("UngrabPointer");
|
dprintln("UngrabPointer");
|
||||||
dprintln(" time: {}", time);
|
dprintln(" time: {}", time);
|
||||||
|
|
||||||
|
if (s_pointer_grab_wid == None)
|
||||||
|
break;
|
||||||
|
|
||||||
|
auto it = g_objects.find(s_pointer_grab_wid);
|
||||||
|
if (it != g_objects.end() && g_platform_ops.set_pointer_grab)
|
||||||
|
if (auto* platform_window = get_platform_window(it->value->object.get<Object::Window>()))
|
||||||
|
g_platform_ops.set_pointer_grab(platform_window, false);
|
||||||
|
|
||||||
|
s_pointer_grab_wid = None;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case X_GrabKeyboard:
|
case X_GrabKeyboard:
|
||||||
@@ -1932,12 +1992,26 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
|||||||
|
|
||||||
const auto& window = TRY_REF(get_window(client_info, wid, opcode));
|
const auto& window = TRY_REF(get_window(client_info, wid, opcode));
|
||||||
|
|
||||||
int32_t root_x, root_y;
|
WINDOW child_wid { None };
|
||||||
int32_t event_x, event_y;
|
for (auto wid_ : window.children)
|
||||||
root_x = event_x = window.cursor_x;
|
{
|
||||||
root_y = event_y = window.cursor_y;
|
const auto& child_window = g_objects[wid_]->object.get<Object::Window>();
|
||||||
|
if (!child_window.hovered)
|
||||||
|
continue;
|
||||||
|
child_wid = wid_;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
const auto child_wid = find_child_window(wid, event_x, event_y);
|
const auto [root_x, root_y] = get_window_position(wid);
|
||||||
|
|
||||||
|
int32_t root_cursor_x, root_cursor_y;
|
||||||
|
if (g_platform_ops.query_pointer)
|
||||||
|
g_platform_ops.query_pointer(&root_cursor_x, &root_cursor_y);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
root_cursor_x = root_x + window.cursor_x;
|
||||||
|
root_cursor_y = root_y + window.cursor_y;
|
||||||
|
}
|
||||||
|
|
||||||
xQueryPointerReply reply {
|
xQueryPointerReply reply {
|
||||||
.type = X_Reply,
|
.type = X_Reply,
|
||||||
@@ -1945,11 +2019,11 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
|||||||
.sequenceNumber = client_info.sequence,
|
.sequenceNumber = client_info.sequence,
|
||||||
.length = 0,
|
.length = 0,
|
||||||
.root = g_root.windowId,
|
.root = g_root.windowId,
|
||||||
.child = static_cast<CARD32>(child_wid == wid ? None : child_wid),
|
.child = static_cast<CARD32>(child_wid),
|
||||||
.rootX = static_cast<INT16>(root_x),
|
.rootX = static_cast<INT16>(root_cursor_x),
|
||||||
.rootY = static_cast<INT16>(root_y),
|
.rootY = static_cast<INT16>(root_cursor_y),
|
||||||
.winX = static_cast<INT16>(event_x),
|
.winX = static_cast<INT16>(root_cursor_x - root_x),
|
||||||
.winY = static_cast<INT16>(event_y),
|
.winY = static_cast<INT16>(root_cursor_y - root_y),
|
||||||
.mask = static_cast<KeyButMask>(g_keymask | g_butmask),
|
.mask = static_cast<KeyButMask>(g_keymask | g_butmask),
|
||||||
};
|
};
|
||||||
TRY(encode(client_info.output_buffer, reply));
|
TRY(encode(client_info.output_buffer, reply));
|
||||||
@@ -1966,19 +2040,55 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
|||||||
dprintln(" src_x: {}", request.srcX);
|
dprintln(" src_x: {}", request.srcX);
|
||||||
dprintln(" src_y: {}", request.srcY);
|
dprintln(" src_y: {}", request.srcY);
|
||||||
|
|
||||||
|
(void)TRY_REF(get_window(client_info, request.dstWid, X_TranslateCoords));
|
||||||
|
(void)TRY_REF(get_window(client_info, request.srcWid, X_TranslateCoords));
|
||||||
|
|
||||||
|
const auto [src_x, src_y] = get_window_position(request.srcWid);
|
||||||
|
const auto [dst_x, dst_y] = get_window_position(request.dstWid);
|
||||||
|
|
||||||
xTranslateCoordsReply reply {
|
xTranslateCoordsReply reply {
|
||||||
.type = X_Reply,
|
.type = X_Reply,
|
||||||
.sameScreen = xTrue,
|
.sameScreen = xTrue,
|
||||||
.sequenceNumber = client_info.sequence,
|
.sequenceNumber = client_info.sequence,
|
||||||
.length = 0,
|
.length = 0,
|
||||||
.child = None,
|
.child = None, // FIXME
|
||||||
.dstX = request.srcX,
|
.dstX = static_cast<INT16>(src_x + request.srcX - dst_x),
|
||||||
.dstY = request.srcY,
|
.dstY = static_cast<INT16>(src_y + request.srcY - dst_y),
|
||||||
};
|
};
|
||||||
TRY(encode(client_info.output_buffer, reply));
|
TRY(encode(client_info.output_buffer, reply));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case X_WarpPointer:
|
||||||
|
{
|
||||||
|
auto request = decode<xWarpPointerReq>(packet).value();
|
||||||
|
|
||||||
|
dprintln("WarpPointer");
|
||||||
|
dprintln(" src_wid: {}", request.srcWid);
|
||||||
|
dprintln(" src_x: {}", request.srcX);
|
||||||
|
dprintln(" src_y: {}", request.srcY);
|
||||||
|
dprintln(" src_w: {}", request.srcWidth);
|
||||||
|
dprintln(" src_h: {}", request.srcHeight);
|
||||||
|
dprintln(" dst_wid: {}", request.dstWid);
|
||||||
|
dprintln(" dst_x: {}", request.dstX);
|
||||||
|
dprintln(" dst_y: {}", request.dstY);
|
||||||
|
|
||||||
|
if (g_platform_ops.warp_pointer == nullptr)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// TODO: source window :)
|
||||||
|
|
||||||
|
if (request.dstWid == None)
|
||||||
|
g_platform_ops.warp_pointer(request.dstX, request.dstY, true);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(void)TRY_REF(get_window(client_info, request.dstWid, X_WarpPointer));
|
||||||
|
const auto [win_x, win_y] = get_window_position(request.dstWid);
|
||||||
|
g_platform_ops.warp_pointer(win_x + request.dstX, win_y + request.dstY, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case X_QueryKeymap:
|
case X_QueryKeymap:
|
||||||
{
|
{
|
||||||
dprintln("QueryKeymap");
|
dprintln("QueryKeymap");
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ BAN::ErrorOr<void> destroy_window(Client& client_info, WINDOW wid);
|
|||||||
|
|
||||||
WINDOW find_child_window(WINDOW wid, int32_t& x, int32_t& y);
|
WINDOW find_child_window(WINDOW wid, int32_t& x, int32_t& y);
|
||||||
|
|
||||||
|
xPoint get_window_position(WINDOW wid);
|
||||||
|
|
||||||
static constexpr uint32_t COLOR_INVISIBLE = 0x69000000;
|
static constexpr uint32_t COLOR_INVISIBLE = 0x69000000;
|
||||||
|
|
||||||
extern CARD16 g_keymask;
|
extern CARD16 g_keymask;
|
||||||
|
|||||||
@@ -24,15 +24,15 @@ endif()
|
|||||||
|
|
||||||
set(PLATFORM "banan-os" CACHE STRING "target platform")
|
set(PLATFORM "banan-os" CACHE STRING "target platform")
|
||||||
|
|
||||||
set(VALID_PLATFORMS "banan-os" "SDL2")
|
set(VALID_PLATFORMS "banan-os" "SDL3")
|
||||||
if(NOT PLATFORM IN_LIST VALID_PLATFORMS)
|
if(NOT PLATFORM IN_LIST VALID_PLATFORMS)
|
||||||
message(FATAL_ERROR "platform \"${PLATFORM}\" not known, valid platforms are ${VALID_PLATFORMS}")
|
message(FATAL_ERROR "platform \"${PLATFORM}\" not known, valid platforms are ${VALID_PLATFORMS}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(PLATFORM STREQUAL "banan-os")
|
if(PLATFORM STREQUAL "banan-os")
|
||||||
list(APPEND XBANAN_SOURCES banan-os/banan-os.cpp)
|
list(APPEND XBANAN_SOURCES banan-os/banan-os.cpp)
|
||||||
elseif(PLATFORM STREQUAL "SDL2")
|
elseif(PLATFORM STREQUAL "SDL3")
|
||||||
list(APPEND XBANAN_SOURCES SDL2/sdl2.cpp)
|
list(APPEND XBANAN_SOURCES SDL3/sdl3.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(xbanan ${XBANAN_SOURCES})
|
add_executable(xbanan ${XBANAN_SOURCES})
|
||||||
@@ -42,9 +42,9 @@ banan_link_library(xbanan libinput)
|
|||||||
|
|
||||||
if(PLATFORM STREQUAL "banan-os")
|
if(PLATFORM STREQUAL "banan-os")
|
||||||
banan_link_library(xbanan libgui)
|
banan_link_library(xbanan libgui)
|
||||||
elseif(PLATFORM STREQUAL "SDL2")
|
elseif(PLATFORM STREQUAL "SDL3")
|
||||||
find_package(SDL2 REQUIRED)
|
find_package(SDL3 REQUIRED)
|
||||||
banan_link_library(xbanan SDL2::SDL2)
|
banan_link_library(xbanan SDL3::SDL3)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_compile_options(xbanan PRIVATE -Wall -Wextra)
|
target_compile_options(xbanan PRIVATE -Wall -Wextra)
|
||||||
|
|||||||
@@ -75,21 +75,8 @@ void on_window_close_event(WINDOW wid)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_window_resize_event(WINDOW wid, uint32_t new_width, uint32_t new_height)
|
static void send_window_configure(WINDOW wid, Object::Window& window)
|
||||||
{
|
{
|
||||||
auto& object = *g_objects[wid];
|
|
||||||
ASSERT(object.type == Object::Type::Window);
|
|
||||||
auto& window = object.object.get<Object::Window>();
|
|
||||||
|
|
||||||
{
|
|
||||||
window.width = new_width;
|
|
||||||
window.height = new_height;
|
|
||||||
|
|
||||||
MUST(window.pixels.resize(new_width * new_height));
|
|
||||||
for (auto& pixel : window.pixels)
|
|
||||||
pixel = window.background;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
xEvent event = { .u = {
|
xEvent event = { .u = {
|
||||||
.configureNotify = {
|
.configureNotify = {
|
||||||
@@ -129,12 +116,42 @@ void on_window_resize_event(WINDOW wid, uint32_t new_width, uint32_t new_height)
|
|||||||
event.u.u.type = ConfigureNotify;
|
event.u.u.type = ConfigureNotify;
|
||||||
MUST(parent_window.send_event(event, SubstructureNotifyMask));
|
MUST(parent_window.send_event(event, SubstructureNotifyMask));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_window_resize_event(WINDOW wid, uint32_t new_width, uint32_t new_height)
|
||||||
|
{
|
||||||
|
auto& object = *g_objects[wid];
|
||||||
|
ASSERT(object.type == Object::Type::Window);
|
||||||
|
auto& window = object.object.get<Object::Window>();
|
||||||
|
|
||||||
|
{
|
||||||
|
window.width = new_width;
|
||||||
|
window.height = new_height;
|
||||||
|
|
||||||
|
MUST(window.pixels.resize(new_width * new_height));
|
||||||
|
for (auto& pixel : window.pixels)
|
||||||
|
pixel = window.background;
|
||||||
|
}
|
||||||
|
|
||||||
|
send_window_configure(wid, window);
|
||||||
|
|
||||||
send_exposure_recursive(wid);
|
send_exposure_recursive(wid);
|
||||||
|
|
||||||
invalidate_window(wid, 0, 0, window.width, window.height);
|
invalidate_window(wid, 0, 0, window.width, window.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void on_window_move_event(WINDOW wid, int32_t x, int32_t y)
|
||||||
|
{
|
||||||
|
auto& object = *g_objects[wid];
|
||||||
|
ASSERT(object.type == Object::Type::Window);
|
||||||
|
auto& window = object.object.get<Object::Window>();
|
||||||
|
|
||||||
|
window.x = x;
|
||||||
|
window.y = y;
|
||||||
|
|
||||||
|
send_window_configure(wid, window);
|
||||||
|
}
|
||||||
|
|
||||||
void on_window_focus_event(WINDOW wid, bool focused)
|
void on_window_focus_event(WINDOW wid, bool focused)
|
||||||
{
|
{
|
||||||
if (focused)
|
if (focused)
|
||||||
@@ -219,15 +236,14 @@ void on_window_fullscreen_event(WINDOW wid, bool is_fullscreen)
|
|||||||
|
|
||||||
static void send_key_button_pointer_event(WINDOW root_wid, BYTE detail, uint32_t event_mask, BYTE event_type, KeyButMask state)
|
static void send_key_button_pointer_event(WINDOW root_wid, BYTE detail, uint32_t event_mask, BYTE event_type, KeyButMask state)
|
||||||
{
|
{
|
||||||
int32_t root_x, root_y;
|
|
||||||
int32_t event_x, event_y;
|
int32_t event_x, event_y;
|
||||||
|
|
||||||
{
|
{
|
||||||
auto& object = *g_objects[root_wid];
|
auto& object = *g_objects[root_wid];
|
||||||
ASSERT(object.type == Object::Type::Window);
|
ASSERT(object.type == Object::Type::Window);
|
||||||
auto& window = object.object.get<Object::Window>();
|
auto& window = object.object.get<Object::Window>();
|
||||||
root_x = event_x = window.cursor_x;
|
event_x = window.cursor_x;
|
||||||
root_y = event_y = window.cursor_y;
|
event_y = window.cursor_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto child_wid = find_child_window(root_wid, event_x, event_y);
|
const auto child_wid = find_child_window(root_wid, event_x, event_y);
|
||||||
@@ -257,14 +273,15 @@ static void send_key_button_pointer_event(WINDOW root_wid, BYTE detail, uint32_t
|
|||||||
ASSERT(object.type == Object::Type::Window);
|
ASSERT(object.type == Object::Type::Window);
|
||||||
auto& window = object.object.get<Object::Window>();
|
auto& window = object.object.get<Object::Window>();
|
||||||
|
|
||||||
|
const auto [root_x, root_y] = get_window_position(wid);
|
||||||
xEvent event { .u = {
|
xEvent event { .u = {
|
||||||
.keyButtonPointer = {
|
.keyButtonPointer = {
|
||||||
.time = static_cast<CARD32>(time(nullptr)),
|
.time = static_cast<CARD32>(time(nullptr)),
|
||||||
.root = g_root.windowId,
|
.root = g_root.windowId,
|
||||||
.event = wid,
|
.event = wid,
|
||||||
.child = static_cast<CARD32>(child_wid == wid ? None : child_wid),
|
.child = static_cast<CARD32>(child_wid == wid ? None : child_wid),
|
||||||
.rootX = static_cast<INT16>(root_x),
|
.rootX = static_cast<INT16>(root_x + event_x),
|
||||||
.rootY = static_cast<INT16>(root_y),
|
.rootY = static_cast<INT16>(root_y + event_y),
|
||||||
.eventX = static_cast<INT16>(event_x),
|
.eventX = static_cast<INT16>(event_x),
|
||||||
.eventY = static_cast<INT16>(event_y),
|
.eventY = static_cast<INT16>(event_y),
|
||||||
.state = state,
|
.state = state,
|
||||||
@@ -389,14 +406,15 @@ static void send_enter_and_leave_events(WINDOW old_wid, int32_t old_x, int32_t o
|
|||||||
ASSERT(object.type == Object::Type::Window);
|
ASSERT(object.type == Object::Type::Window);
|
||||||
auto& window = object.object.get<Object::Window>();
|
auto& window = object.object.get<Object::Window>();
|
||||||
|
|
||||||
|
const auto [root_x, root_y] = get_window_position(wid);
|
||||||
xEvent event { .u = {
|
xEvent event { .u = {
|
||||||
.enterLeave = {
|
.enterLeave = {
|
||||||
.time = static_cast<CARD32>(time(nullptr)),
|
.time = static_cast<CARD32>(time(nullptr)),
|
||||||
.root = g_root.windowId,
|
.root = g_root.windowId,
|
||||||
.event = wid,
|
.event = wid,
|
||||||
.child = first ? static_cast<WINDOW>(None) : old_child_path.back(),
|
.child = first ? static_cast<WINDOW>(None) : old_child_path.back(),
|
||||||
.rootX = static_cast<INT16>(old_x),
|
.rootX = static_cast<INT16>(root_x + old_x),
|
||||||
.rootY = static_cast<INT16>(old_y),
|
.rootY = static_cast<INT16>(root_y + old_y),
|
||||||
.eventX = static_cast<INT16>(old_x),
|
.eventX = static_cast<INT16>(old_x),
|
||||||
.eventY = static_cast<INT16>(old_y),
|
.eventY = static_cast<INT16>(old_y),
|
||||||
.state = static_cast<KeyButMask>(g_keymask | g_butmask),
|
.state = static_cast<KeyButMask>(g_keymask | g_butmask),
|
||||||
@@ -429,14 +447,15 @@ static void send_enter_and_leave_events(WINDOW old_wid, int32_t old_x, int32_t o
|
|||||||
ASSERT(object.type == Object::Type::Window);
|
ASSERT(object.type == Object::Type::Window);
|
||||||
auto& window = object.object.get<Object::Window>();
|
auto& window = object.object.get<Object::Window>();
|
||||||
|
|
||||||
|
const auto [root_x, root_y] = get_window_position(wid);
|
||||||
xEvent event { .u = {
|
xEvent event { .u = {
|
||||||
.enterLeave = {
|
.enterLeave = {
|
||||||
.time = static_cast<CARD32>(time(nullptr)),
|
.time = static_cast<CARD32>(time(nullptr)),
|
||||||
.root = g_root.windowId,
|
.root = g_root.windowId,
|
||||||
.event = wid,
|
.event = wid,
|
||||||
.child = last ? static_cast<WINDOW>(None) : new_child_path.back(),
|
.child = last ? static_cast<WINDOW>(None) : new_child_path.back(),
|
||||||
.rootX = static_cast<INT16>(new_x),
|
.rootX = static_cast<INT16>(root_x + new_x),
|
||||||
.rootY = static_cast<INT16>(new_y),
|
.rootY = static_cast<INT16>(root_y + new_y),
|
||||||
.eventX = static_cast<INT16>(new_x),
|
.eventX = static_cast<INT16>(new_x),
|
||||||
.eventY = static_cast<INT16>(new_y),
|
.eventY = static_cast<INT16>(new_y),
|
||||||
.state = static_cast<KeyButMask>(g_keymask | g_butmask),
|
.state = static_cast<KeyButMask>(g_keymask | g_butmask),
|
||||||
@@ -453,7 +472,22 @@ static void send_enter_and_leave_events(WINDOW old_wid, int32_t old_x, int32_t o
|
|||||||
g_objects[wid]->object.get<Object::Window>().hovered = false;
|
g_objects[wid]->object.get<Object::Window>().hovered = false;
|
||||||
for (const auto wid : new_child_path)
|
for (const auto wid : new_child_path)
|
||||||
g_objects[wid]->object.get<Object::Window>().hovered = true;
|
g_objects[wid]->object.get<Object::Window>().hovered = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static WINDOW s_current_top_level_window = None;
|
||||||
|
|
||||||
|
void on_window_leave_event(WINDOW wid)
|
||||||
|
{
|
||||||
|
if (s_current_top_level_window != wid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto& object = *g_objects[wid];
|
||||||
|
ASSERT(object.type == Object::Type::Window);
|
||||||
|
auto& window = object.object.get<Object::Window>();
|
||||||
|
|
||||||
|
send_enter_and_leave_events(wid, window.cursor_x, window.cursor_y, wid, -1, -1);
|
||||||
|
|
||||||
|
s_current_top_level_window = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_mouse_move_event(WINDOW wid, int32_t x, int32_t y)
|
void on_mouse_move_event(WINDOW wid, int32_t x, int32_t y)
|
||||||
@@ -464,24 +498,17 @@ void on_mouse_move_event(WINDOW wid, int32_t x, int32_t y)
|
|||||||
|
|
||||||
update_cursor(wid, x, y);
|
update_cursor(wid, x, y);
|
||||||
|
|
||||||
|
if (auto it = g_objects.find(s_current_top_level_window); it == g_objects.end())
|
||||||
|
send_enter_and_leave_events(wid, -1, -1, wid, x, y);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
static WINDOW old_wid = g_root.windowId;
|
|
||||||
|
|
||||||
auto it = g_objects.find(old_wid);
|
|
||||||
if (it == g_objects.end())
|
|
||||||
{
|
|
||||||
old_wid = g_root.windowId;
|
|
||||||
it = g_objects.find(g_root.windowId);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(it->value->type == Object::Type::Window);
|
ASSERT(it->value->type == Object::Type::Window);
|
||||||
auto& old_window = it->value->object.get<Object::Window>();
|
auto& old_window = it->value->object.get<Object::Window>();
|
||||||
|
send_enter_and_leave_events(s_current_top_level_window, old_window.cursor_x, old_window.cursor_y, wid, x, y);
|
||||||
send_enter_and_leave_events(old_wid, old_window.cursor_x, old_window.cursor_y, wid, x, y);
|
|
||||||
|
|
||||||
old_wid = wid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s_current_top_level_window = wid;
|
||||||
|
|
||||||
update_cursor_position_recursive(wid, x, y);
|
update_cursor_position_recursive(wid, x, y);
|
||||||
|
|
||||||
// TODO: optimize with PointerMotionHint
|
// TODO: optimize with PointerMotionHint
|
||||||
|
|||||||
@@ -7,8 +7,10 @@ void unregister_event_fd(int fd);
|
|||||||
|
|
||||||
void on_window_close_event(WINDOW wid);
|
void on_window_close_event(WINDOW wid);
|
||||||
void on_window_resize_event(WINDOW wid, uint32_t width, uint32_t height);
|
void on_window_resize_event(WINDOW wid, uint32_t width, uint32_t height);
|
||||||
|
void on_window_move_event(WINDOW wid, int32_t x, int32_t y);
|
||||||
void on_window_focus_event(WINDOW wid, bool focused);
|
void on_window_focus_event(WINDOW wid, bool focused);
|
||||||
void on_window_fullscreen_event(WINDOW wid, bool is_fullscreen);
|
void on_window_fullscreen_event(WINDOW wid, bool is_fullscreen);
|
||||||
|
void on_window_leave_event(WINDOW wid);
|
||||||
|
|
||||||
void on_mouse_move_event(WINDOW wid, int32_t x, int32_t y);
|
void on_mouse_move_event(WINDOW wid, int32_t x, int32_t y);
|
||||||
void on_mouse_button_event(WINDOW wid, uint8_t xbutton, bool pressed);
|
void on_mouse_button_event(WINDOW wid, uint8_t xbutton, bool pressed);
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ struct PlatformCursor
|
|||||||
|
|
||||||
enum class WindowType
|
enum class WindowType
|
||||||
{
|
{
|
||||||
Popup,
|
|
||||||
Normal,
|
Normal,
|
||||||
Utility,
|
Utility,
|
||||||
|
Popup,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SystemCursorType
|
enum class SystemCursorType
|
||||||
@@ -55,8 +55,16 @@ struct PlatformOps
|
|||||||
void (*invalidate)(PlatformWindow*, const uint32_t* pixels, uint32_t x, uint32_t y, uint32_t width, uint32_t height);
|
void (*invalidate)(PlatformWindow*, const uint32_t* pixels, uint32_t x, uint32_t y, uint32_t width, uint32_t height);
|
||||||
/* Request resize of a window, can be async */
|
/* Request resize of a window, can be async */
|
||||||
void (*request_resize)(PlatformWindow*, uint32_t width, uint32_t height);
|
void (*request_resize)(PlatformWindow*, uint32_t width, uint32_t height);
|
||||||
|
/* Request window repositioning */
|
||||||
|
void (*request_reposition)(PlatformWindow*, int32_t x, int32_t y);
|
||||||
/* Request new fullscreen state, can be async */
|
/* Request new fullscreen state, can be async */
|
||||||
void (*request_fullscreen)(PlatformWindow*, bool fullscreen);
|
void (*request_fullscreen)(PlatformWindow*, bool fullscreen);
|
||||||
|
/* Warp pointer */
|
||||||
|
void (*warp_pointer)(int32_t x, int32_t y, bool relative);
|
||||||
|
/* Get global position of the pointer */
|
||||||
|
void (*query_pointer)(int32_t* x, int32_t* y);
|
||||||
|
/* Grab pointer events on window */
|
||||||
|
void (*set_pointer_grab)(PlatformWindow*, bool grabbed);
|
||||||
/* Create a system cursor */
|
/* Create a system cursor */
|
||||||
BAN::ErrorOr<BAN::UniqPtr<PlatformCursor>> (*create_system_cursor)(SystemCursorType);
|
BAN::ErrorOr<BAN::UniqPtr<PlatformCursor>> (*create_system_cursor)(SystemCursorType);
|
||||||
/* Create cursor from custom bitmap */
|
/* Create cursor from custom bitmap */
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <BAN/Atomic.h>
|
#include <BAN/Atomic.h>
|
||||||
#include <BAN/HashMap.h>
|
#include <BAN/HashMap.h>
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <sys/eventfd.h>
|
#include <sys/eventfd.h>
|
||||||
@@ -44,7 +44,7 @@ struct SDLCursor final : public PlatformCursor
|
|||||||
~SDLCursor()
|
~SDLCursor()
|
||||||
{
|
{
|
||||||
if (cursor != nullptr)
|
if (cursor != nullptr)
|
||||||
SDL_FreeCursor(cursor);
|
SDL_DestroyCursor(cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Cursor* cursor { nullptr };
|
SDL_Cursor* cursor { nullptr };
|
||||||
@@ -55,13 +55,13 @@ static int s_eventfd { -1 };
|
|||||||
struct Keymap
|
struct Keymap
|
||||||
{
|
{
|
||||||
consteval Keymap();
|
consteval Keymap();
|
||||||
uint8_t map[SDL_NUM_SCANCODES];
|
uint8_t map[SDL_SCANCODE_COUNT];
|
||||||
};
|
};
|
||||||
static Keymap s_sdl_keymap;
|
static Keymap s_sdl_keymap;
|
||||||
|
|
||||||
static SDL_Cursor* s_default_cursor { nullptr };
|
static SDL_Cursor* s_default_cursor { nullptr };
|
||||||
|
|
||||||
static void* sdl2_thread(void*)
|
static void* sdl3_thread(void*)
|
||||||
{
|
{
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
@@ -73,22 +73,24 @@ static void* sdl2_thread(void*)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool sdl2_initialize(uint32_t* display_w, uint32_t* display_h)
|
static bool sdl3_initialize(uint32_t* display_w, uint32_t* display_h)
|
||||||
{
|
{
|
||||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) == -1)
|
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS))
|
||||||
{
|
{
|
||||||
dwarnln("Could not initialize SDL: {}", SDL_GetError());
|
dwarnln("Could not initialize SDL: {}", SDL_GetError());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_DisplayMode DM;
|
*display_w = *display_h = 0;
|
||||||
if (SDL_GetCurrentDisplayMode(0, &DM) == -1)
|
|
||||||
|
const SDL_DisplayID* display_ids = SDL_GetDisplays(nullptr);
|
||||||
|
for (int i = 0; display_ids[i]; i++)
|
||||||
{
|
{
|
||||||
dwarnln("Could not get display mode: {}", SDL_GetError());
|
SDL_Rect rect;
|
||||||
return false;
|
SDL_GetDisplayBounds(display_ids[i], &rect);
|
||||||
|
*display_w = BAN::Math::max<uint32_t>(*display_w, rect.x + rect.w);
|
||||||
|
*display_h = BAN::Math::max<uint32_t>(*display_h, rect.y + rect.h);
|
||||||
}
|
}
|
||||||
*display_w = DM.w;
|
|
||||||
*display_h = DM.h;
|
|
||||||
|
|
||||||
s_default_cursor = SDL_GetCursor();
|
s_default_cursor = SDL_GetCursor();
|
||||||
|
|
||||||
@@ -102,12 +104,12 @@ static bool sdl2_initialize(uint32_t* display_w, uint32_t* display_h)
|
|||||||
register_event_fd(s_eventfd, nullptr);
|
register_event_fd(s_eventfd, nullptr);
|
||||||
|
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
pthread_create(&thread, nullptr, sdl2_thread, nullptr);
|
pthread_create(&thread, nullptr, sdl3_thread, nullptr);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<PlatformWindow>> sdl2_create_window(PlatformWindow* parent, WindowType type, WINDOW wid, int32_t x, int32_t y, uint32_t width, uint32_t height)
|
static BAN::ErrorOr<BAN::UniqPtr<PlatformWindow>> sdl3_create_window(PlatformWindow* parent, WindowType type, WINDOW wid, int32_t x, int32_t y, uint32_t width, uint32_t height)
|
||||||
{
|
{
|
||||||
auto window = TRY(BAN::UniqPtr<SDLWindow>::create());
|
auto window = TRY(BAN::UniqPtr<SDLWindow>::create());
|
||||||
|
|
||||||
@@ -115,39 +117,41 @@ static BAN::ErrorOr<BAN::UniqPtr<PlatformWindow>> sdl2_create_window(PlatformWin
|
|||||||
window->width = width;
|
window->width = width;
|
||||||
window->height = height;
|
window->height = height;
|
||||||
|
|
||||||
if (parent == nullptr)
|
|
||||||
x = y = SDL_WINDOWPOS_UNDEFINED;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto& sdl_parent = *static_cast<SDLWindow*>(parent);
|
|
||||||
int parent_x, parent_y;
|
|
||||||
SDL_GetWindowPosition(sdl_parent.window, &parent_x, &parent_y);
|
|
||||||
x += parent_x;
|
|
||||||
y += parent_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
int flags;
|
int flags;
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case WindowType::Popup:
|
|
||||||
flags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_SKIP_TASKBAR | SDL_WINDOW_UTILITY;
|
|
||||||
break;
|
|
||||||
case WindowType::Utility:
|
|
||||||
flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_UTILITY;
|
|
||||||
break;
|
|
||||||
case WindowType::Normal:
|
case WindowType::Normal:
|
||||||
|
case WindowType::Utility:
|
||||||
flags = SDL_WINDOW_RESIZABLE;
|
flags = SDL_WINDOW_RESIZABLE;
|
||||||
break;
|
break;
|
||||||
|
case WindowType::Popup:
|
||||||
|
flags = SDL_WINDOW_BORDERLESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent == nullptr || type != WindowType::Popup)
|
||||||
|
{
|
||||||
|
if (type != WindowType::Normal)
|
||||||
|
flags |= SDL_WINDOW_UTILITY;
|
||||||
|
window->window = SDL_CreateWindow("", width, height, flags);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto& sdl_parent = *static_cast<SDLWindow*>(parent);
|
||||||
|
|
||||||
|
int parent_x, parent_y;
|
||||||
|
SDL_GetWindowPosition(sdl_parent.window, &parent_x, &parent_y);
|
||||||
|
|
||||||
|
window->window = SDL_CreatePopupWindow(sdl_parent.window, x - parent_x, y - parent_y, width, height, flags | SDL_WINDOW_POPUP_MENU);
|
||||||
}
|
}
|
||||||
|
|
||||||
window->window = SDL_CreateWindow("", x, y, width, height, flags);
|
|
||||||
if (window->window == nullptr)
|
if (window->window == nullptr)
|
||||||
{
|
{
|
||||||
dwarnln("Could not create SDL window: {}", SDL_GetError());
|
dwarnln("Could not create SDL window: {}", SDL_GetError());
|
||||||
return BAN::Error::from_errno(EFAULT);
|
return BAN::Error::from_errno(EFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
window->renderer = SDL_CreateRenderer(window->window, -1, SDL_RENDERER_ACCELERATED);
|
window->renderer = SDL_CreateRenderer(window->window, nullptr);
|
||||||
if (window->renderer == nullptr)
|
if (window->renderer == nullptr)
|
||||||
{
|
{
|
||||||
dwarnln("Could not create SDL renderer: {}", SDL_GetError());
|
dwarnln("Could not create SDL renderer: {}", SDL_GetError());
|
||||||
@@ -166,13 +170,19 @@ static BAN::ErrorOr<BAN::UniqPtr<PlatformWindow>> sdl2_create_window(PlatformWin
|
|||||||
return BAN::UniqPtr<PlatformWindow>(BAN::move(window));
|
return BAN::UniqPtr<PlatformWindow>(BAN::move(window));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sdl2_request_resize(PlatformWindow* window, uint32_t width, uint32_t height)
|
static void sdl3_request_resize(PlatformWindow* window, uint32_t width, uint32_t height)
|
||||||
{
|
{
|
||||||
auto& sdl_window = *static_cast<SDLWindow*>(window);
|
auto& sdl_window = *static_cast<SDLWindow*>(window);
|
||||||
SDL_SetWindowSize(sdl_window.window, width, height);
|
SDL_SetWindowSize(sdl_window.window, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sdl2_poll_events(void*)
|
static void sdl3_request_reposition(PlatformWindow* window, int32_t x, int32_t y)
|
||||||
|
{
|
||||||
|
auto& sdl_window = *static_cast<SDLWindow*>(window);
|
||||||
|
SDL_SetWindowPosition(sdl_window.window, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sdl3_poll_events(void*)
|
||||||
{
|
{
|
||||||
uint64_t dummy;
|
uint64_t dummy;
|
||||||
read(s_eventfd, &dummy, sizeof(dummy));
|
read(s_eventfd, &dummy, sizeof(dummy));
|
||||||
@@ -182,51 +192,48 @@ static void sdl2_poll_events(void*)
|
|||||||
{
|
{
|
||||||
switch (event.type)
|
switch (event.type)
|
||||||
{
|
{
|
||||||
case SDL_WINDOWEVENT:
|
case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
|
||||||
{
|
if (auto it = s_window_map.find(event.window.windowID); it != s_window_map.end())
|
||||||
auto it = s_window_map.find(event.window.windowID);
|
on_window_close_event(it->value->wid);
|
||||||
if (it == s_window_map.end())
|
break;
|
||||||
break;
|
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
|
||||||
auto& window = *it->value;
|
if (auto it = s_window_map.find(event.window.windowID); it != s_window_map.end())
|
||||||
switch (event.window.event)
|
|
||||||
{
|
{
|
||||||
case SDL_WINDOWEVENT_CLOSE:
|
auto& window = *it->value;
|
||||||
on_window_close_event(window.wid);
|
window.width = event.window.data1;
|
||||||
break;
|
window.height = event.window.data2;
|
||||||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
|
||||||
window.width = event.window.data1;
|
|
||||||
window.height = event.window.data2;
|
|
||||||
|
|
||||||
SDL_DestroyTexture(window.texture);
|
SDL_DestroyTexture(window.texture);
|
||||||
window.texture = SDL_CreateTexture(window.renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, window.width, window.height);
|
window.texture = SDL_CreateTexture(window.renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, window.width, window.height);
|
||||||
ASSERT(window.texture);
|
ASSERT(window.texture);
|
||||||
|
|
||||||
on_window_resize_event(window.wid, event.window.data1, event.window.data2);
|
on_window_resize_event(window.wid, window.width, window.height);
|
||||||
break;
|
|
||||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
|
||||||
on_window_focus_event(window.wid, true);
|
|
||||||
break;
|
|
||||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
|
||||||
on_window_focus_event(window.wid, false);
|
|
||||||
break;
|
|
||||||
case SDL_WINDOWEVENT_MAXIMIZED:
|
|
||||||
on_window_fullscreen_event(window.wid, true);
|
|
||||||
break;
|
|
||||||
case SDL_WINDOWEVENT_RESTORED:
|
|
||||||
on_window_fullscreen_event(window.wid, false);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
case SDL_EVENT_WINDOW_MOVED:
|
||||||
case SDL_MOUSEMOTION:
|
if (auto it = s_window_map.find(event.motion.windowID); it != s_window_map.end())
|
||||||
{
|
on_window_move_event(it->value->wid, event.window.data1, event.window.data2);
|
||||||
auto it = s_window_map.find(event.window.windowID);
|
break;
|
||||||
if (it != s_window_map.end())
|
case SDL_EVENT_WINDOW_FOCUS_GAINED:
|
||||||
|
case SDL_EVENT_WINDOW_FOCUS_LOST:
|
||||||
|
if (auto it = s_window_map.find(event.motion.windowID); it != s_window_map.end())
|
||||||
|
on_window_focus_event(it->value->wid, (event.type == SDL_EVENT_WINDOW_FOCUS_GAINED));
|
||||||
|
break;
|
||||||
|
case SDL_EVENT_WINDOW_ENTER_FULLSCREEN:
|
||||||
|
case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN:
|
||||||
|
if (auto it = s_window_map.find(event.motion.windowID); it != s_window_map.end())
|
||||||
|
on_window_fullscreen_event(it->value->wid, (event.type == SDL_EVENT_WINDOW_ENTER_FULLSCREEN));
|
||||||
|
break;
|
||||||
|
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
|
||||||
|
if (auto it = s_window_map.find(event.motion.windowID); it != s_window_map.end())
|
||||||
|
on_window_leave_event(it->value->wid);
|
||||||
|
break;
|
||||||
|
case SDL_EVENT_MOUSE_MOTION:
|
||||||
|
if (auto it = s_window_map.find(event.motion.windowID); it != s_window_map.end())
|
||||||
on_mouse_move_event(it->value->wid, event.motion.x, event.motion.y);
|
on_mouse_move_event(it->value->wid, event.motion.x, event.motion.y);
|
||||||
break;
|
break;
|
||||||
}
|
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||||
case SDL_MOUSEBUTTONUP:
|
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||||
case SDL_MOUSEBUTTONDOWN:
|
|
||||||
{
|
{
|
||||||
uint8_t xbutton { 0 };
|
uint8_t xbutton { 0 };
|
||||||
switch (event.button.button)
|
switch (event.button.button)
|
||||||
@@ -240,10 +247,10 @@ static void sdl2_poll_events(void*)
|
|||||||
|
|
||||||
auto it = s_window_map.find(event.window.windowID);
|
auto it = s_window_map.find(event.window.windowID);
|
||||||
if (xbutton && it != s_window_map.end())
|
if (xbutton && it != s_window_map.end())
|
||||||
on_mouse_button_event(it->value->wid, xbutton, (event.type == SDL_MOUSEBUTTONDOWN));
|
on_mouse_button_event(it->value->wid, xbutton, (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SDL_MOUSEWHEEL:
|
case SDL_EVENT_MOUSE_WHEEL:
|
||||||
{
|
{
|
||||||
uint8_t xbutton { 0 };
|
uint8_t xbutton { 0 };
|
||||||
if (event.wheel.y > 0)
|
if (event.wheel.y > 0)
|
||||||
@@ -260,31 +267,31 @@ static void sdl2_poll_events(void*)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SDL_KEYUP:
|
case SDL_EVENT_KEY_UP:
|
||||||
case SDL_KEYDOWN:
|
case SDL_EVENT_KEY_DOWN:
|
||||||
{
|
{
|
||||||
uint8_t scancode = s_sdl_keymap.map[event.key.keysym.scancode];
|
uint8_t scancode = s_sdl_keymap.map[event.key.scancode];
|
||||||
|
|
||||||
uint8_t xmod { 0 };
|
uint8_t xmod { 0 };
|
||||||
if (event.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT))
|
if (event.key.mod & SDL_KMOD_SHIFT)
|
||||||
xmod |= (1 << 0);
|
xmod |= (1 << 0);
|
||||||
if (event.key.keysym.mod & (KMOD_CAPS))
|
if (event.key.mod & SDL_KMOD_CAPS)
|
||||||
xmod |= (1 << 1);
|
xmod |= (1 << 1);
|
||||||
if (event.key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL))
|
if (event.key.mod & SDL_KMOD_CTRL)
|
||||||
xmod |= (1 << 2);
|
xmod |= (1 << 2);
|
||||||
if (event.key.keysym.mod & (KMOD_LALT | KMOD_RALT))
|
if (event.key.mod & SDL_KMOD_ALT)
|
||||||
xmod |= (1 << 3);
|
xmod |= (1 << 3);
|
||||||
|
|
||||||
auto it = s_window_map.find(event.window.windowID);
|
auto it = s_window_map.find(event.window.windowID);
|
||||||
if (it != s_window_map.end())
|
if (it != s_window_map.end())
|
||||||
on_key_event(it->value->wid, scancode, xmod, (event.type == SDL_KEYDOWN));
|
on_key_event(it->value->wid, scancode, xmod, (event.type == SDL_EVENT_KEY_DOWN));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sdl2_invalidate(PlatformWindow* window, const uint32_t* src_pixels, uint32_t x, uint32_t y, uint32_t width, uint32_t height)
|
static void sdl3_invalidate(PlatformWindow* window, const uint32_t* src_pixels, uint32_t x, uint32_t y, uint32_t width, uint32_t height)
|
||||||
{
|
{
|
||||||
auto& sdl_window = *static_cast<SDLWindow*>(window);
|
auto& sdl_window = *static_cast<SDLWindow*>(window);
|
||||||
|
|
||||||
@@ -300,7 +307,7 @@ static void sdl2_invalidate(PlatformWindow* window, const uint32_t* src_pixels,
|
|||||||
|
|
||||||
void* dst_pixels;
|
void* dst_pixels;
|
||||||
int dst_pitch;
|
int dst_pitch;
|
||||||
if (SDL_LockTexture(sdl_window.texture, &rect, &dst_pixels, &dst_pitch) == -1)
|
if (!SDL_LockTexture(sdl_window.texture, &rect, &dst_pixels, &dst_pitch))
|
||||||
{
|
{
|
||||||
dwarnln("Could not lock texture: {}", SDL_GetError());
|
dwarnln("Could not lock texture: {}", SDL_GetError());
|
||||||
return;
|
return;
|
||||||
@@ -318,63 +325,68 @@ static void sdl2_invalidate(PlatformWindow* window, const uint32_t* src_pixels,
|
|||||||
SDL_UnlockTexture(sdl_window.texture);
|
SDL_UnlockTexture(sdl_window.texture);
|
||||||
|
|
||||||
SDL_RenderClear(sdl_window.renderer);
|
SDL_RenderClear(sdl_window.renderer);
|
||||||
SDL_RenderCopy(sdl_window.renderer, sdl_window.texture, NULL, NULL);
|
SDL_RenderTexture(sdl_window.renderer, sdl_window.texture, NULL, NULL);
|
||||||
SDL_RenderPresent(sdl_window.renderer);
|
SDL_RenderPresent(sdl_window.renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sdl2_request_fullscreen(PlatformWindow* window, bool fullscreen)
|
static void sdl3_request_fullscreen(PlatformWindow* window, bool fullscreen)
|
||||||
{
|
{
|
||||||
auto& sdl_window = *static_cast<SDLWindow*>(window);
|
auto& sdl_window = *static_cast<SDLWindow*>(window);
|
||||||
SDL_SetWindowFullscreen(sdl_window.window, fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
|
SDL_SetWindowFullscreen(sdl_window.window, fullscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<PlatformCursor>> sdl2_create_system_cursor(SystemCursorType type)
|
static void sdl3_warp_pointer(int32_t x, int32_t y, bool relative)
|
||||||
{
|
{
|
||||||
SDL_SystemCursor sdl_type;
|
if (relative)
|
||||||
switch (type)
|
|
||||||
{
|
{
|
||||||
case SystemCursorType::Help:
|
float cx, cy;
|
||||||
case SystemCursorType::Pointer:
|
SDL_GetGlobalMouseState(&cx, &cy);
|
||||||
sdl_type = SDL_SYSTEM_CURSOR_ARROW;
|
x += cx;
|
||||||
break;
|
x += cy;
|
||||||
case SystemCursorType::Text:
|
|
||||||
sdl_type = SDL_SYSTEM_CURSOR_IBEAM;
|
|
||||||
break;
|
|
||||||
case SystemCursorType::Wait:
|
|
||||||
sdl_type = SDL_SYSTEM_CURSOR_WAIT;
|
|
||||||
break;
|
|
||||||
case SystemCursorType::Hand:
|
|
||||||
sdl_type = SDL_SYSTEM_CURSOR_HAND;
|
|
||||||
break;
|
|
||||||
case SystemCursorType::Move:
|
|
||||||
sdl_type = SDL_SYSTEM_CURSOR_SIZEALL;
|
|
||||||
break;
|
|
||||||
case SystemCursorType::Forbidden:
|
|
||||||
sdl_type = SDL_SYSTEM_CURSOR_NO;
|
|
||||||
break;
|
|
||||||
case SystemCursorType::ResizeN:
|
|
||||||
case SystemCursorType::ResizeS:
|
|
||||||
case SystemCursorType::ResizeVertical:
|
|
||||||
sdl_type = SDL_SYSTEM_CURSOR_SIZENS;
|
|
||||||
break;
|
|
||||||
case SystemCursorType::ResizeE:
|
|
||||||
case SystemCursorType::ResizeW:
|
|
||||||
case SystemCursorType::ResizeHorizontal:
|
|
||||||
sdl_type = SDL_SYSTEM_CURSOR_SIZEWE;
|
|
||||||
break;
|
|
||||||
case SystemCursorType::ResizeNW:
|
|
||||||
case SystemCursorType::ResizeSE:
|
|
||||||
sdl_type = SDL_SYSTEM_CURSOR_SIZENWSE;
|
|
||||||
break;
|
|
||||||
case SystemCursorType::ResizeNE:
|
|
||||||
case SystemCursorType::ResizeSW:
|
|
||||||
sdl_type = SDL_SYSTEM_CURSOR_SIZENESW;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_WarpMouseGlobal(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sdl3_query_pointer(int32_t* x, int32_t* y)
|
||||||
|
{
|
||||||
|
float cx, cy;
|
||||||
|
SDL_GetGlobalMouseState(&cx, &cy);
|
||||||
|
*x = cx;
|
||||||
|
*y = cy;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sdl3_set_pointer_grab(PlatformWindow* window, bool grabbed)
|
||||||
|
{
|
||||||
|
auto& sdl_window = *static_cast<SDLWindow*>(window);
|
||||||
|
SDL_SetWindowMouseGrab(sdl_window.window, grabbed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BAN::ErrorOr<BAN::UniqPtr<PlatformCursor>> sdl3_create_system_cursor(SystemCursorType type)
|
||||||
|
{
|
||||||
|
static constexpr SDL_SystemCursor cursor_type_map[] {
|
||||||
|
[static_cast<size_t>(SystemCursorType::Pointer)] = SDL_SYSTEM_CURSOR_DEFAULT,
|
||||||
|
[static_cast<size_t>(SystemCursorType::Text)] = SDL_SYSTEM_CURSOR_TEXT,
|
||||||
|
[static_cast<size_t>(SystemCursorType::Wait)] = SDL_SYSTEM_CURSOR_WAIT,
|
||||||
|
[static_cast<size_t>(SystemCursorType::Hand)] = SDL_SYSTEM_CURSOR_POINTER,
|
||||||
|
[static_cast<size_t>(SystemCursorType::Help)] = SDL_SYSTEM_CURSOR_DEFAULT, // :(
|
||||||
|
[static_cast<size_t>(SystemCursorType::Move)] = SDL_SYSTEM_CURSOR_MOVE,
|
||||||
|
[static_cast<size_t>(SystemCursorType::Forbidden)] = SDL_SYSTEM_CURSOR_NOT_ALLOWED,
|
||||||
|
[static_cast<size_t>(SystemCursorType::ResizeN)] = SDL_SYSTEM_CURSOR_N_RESIZE,
|
||||||
|
[static_cast<size_t>(SystemCursorType::ResizeE)] = SDL_SYSTEM_CURSOR_E_RESIZE,
|
||||||
|
[static_cast<size_t>(SystemCursorType::ResizeS)] = SDL_SYSTEM_CURSOR_S_RESIZE,
|
||||||
|
[static_cast<size_t>(SystemCursorType::ResizeW)] = SDL_SYSTEM_CURSOR_W_RESIZE,
|
||||||
|
[static_cast<size_t>(SystemCursorType::ResizeNW)] = SDL_SYSTEM_CURSOR_NW_RESIZE,
|
||||||
|
[static_cast<size_t>(SystemCursorType::ResizeNE)] = SDL_SYSTEM_CURSOR_NE_RESIZE,
|
||||||
|
[static_cast<size_t>(SystemCursorType::ResizeSW)] = SDL_SYSTEM_CURSOR_SW_RESIZE,
|
||||||
|
[static_cast<size_t>(SystemCursorType::ResizeSE)] = SDL_SYSTEM_CURSOR_SE_RESIZE,
|
||||||
|
[static_cast<size_t>(SystemCursorType::ResizeVertical)] = SDL_SYSTEM_CURSOR_NS_RESIZE,
|
||||||
|
[static_cast<size_t>(SystemCursorType::ResizeHorizontal)] = SDL_SYSTEM_CURSOR_EW_RESIZE,
|
||||||
|
};
|
||||||
|
|
||||||
auto cursor = TRY(BAN::UniqPtr<SDLCursor>::create());
|
auto cursor = TRY(BAN::UniqPtr<SDLCursor>::create());
|
||||||
|
|
||||||
cursor->cursor = SDL_CreateSystemCursor(sdl_type);
|
cursor->cursor = SDL_CreateSystemCursor(cursor_type_map[static_cast<size_t>(type)]);
|
||||||
if (cursor->cursor == nullptr)
|
if (cursor->cursor == nullptr)
|
||||||
{
|
{
|
||||||
dwarnln("Could not create SDL system cursor: {}", SDL_GetError());
|
dwarnln("Could not create SDL system cursor: {}", SDL_GetError());
|
||||||
@@ -384,11 +396,11 @@ static BAN::ErrorOr<BAN::UniqPtr<PlatformCursor>> sdl2_create_system_cursor(Syst
|
|||||||
return BAN::UniqPtr<PlatformCursor>(BAN::move(cursor));
|
return BAN::UniqPtr<PlatformCursor>(BAN::move(cursor));
|
||||||
}
|
}
|
||||||
|
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<PlatformCursor>> sdl2_create_bitmap_cursor(const uint32_t* pixels, uint32_t width, uint32_t height, int32_t origin_x, int32_t origin_y)
|
static BAN::ErrorOr<BAN::UniqPtr<PlatformCursor>> sdl3_create_bitmap_cursor(const uint32_t* pixels, uint32_t width, uint32_t height, int32_t origin_x, int32_t origin_y)
|
||||||
{
|
{
|
||||||
auto cursor = TRY(BAN::UniqPtr<SDLCursor>::create());
|
auto cursor = TRY(BAN::UniqPtr<SDLCursor>::create());
|
||||||
|
|
||||||
SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormatFrom(const_cast<uint32_t*>(pixels), width, height, 32, width * 4, SDL_PIXELFORMAT_ARGB8888);
|
SDL_Surface* surface = SDL_CreateSurfaceFrom(width, height, SDL_PIXELFORMAT_ARGB8888, const_cast<uint32_t*>(pixels), width * 4);
|
||||||
if (surface == nullptr)
|
if (surface == nullptr)
|
||||||
{
|
{
|
||||||
dwarnln("Could not create SDL surface for cursor: {}", SDL_GetError());
|
dwarnln("Could not create SDL surface for cursor: {}", SDL_GetError());
|
||||||
@@ -399,7 +411,7 @@ static BAN::ErrorOr<BAN::UniqPtr<PlatformCursor>> sdl2_create_bitmap_cursor(cons
|
|||||||
origin_y = BAN::Math::clamp<int32_t>(origin_y, 0, height - 1);
|
origin_y = BAN::Math::clamp<int32_t>(origin_y, 0, height - 1);
|
||||||
cursor->cursor = SDL_CreateColorCursor(surface, origin_x, origin_y);
|
cursor->cursor = SDL_CreateColorCursor(surface, origin_x, origin_y);
|
||||||
|
|
||||||
SDL_FreeSurface(surface);
|
SDL_DestroySurface(surface);
|
||||||
|
|
||||||
if (cursor->cursor == nullptr)
|
if (cursor->cursor == nullptr)
|
||||||
{
|
{
|
||||||
@@ -410,7 +422,7 @@ static BAN::ErrorOr<BAN::UniqPtr<PlatformCursor>> sdl2_create_bitmap_cursor(cons
|
|||||||
return BAN::UniqPtr<PlatformCursor>(BAN::move(cursor));
|
return BAN::UniqPtr<PlatformCursor>(BAN::move(cursor));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sdl2_set_cursor(PlatformWindow*, PlatformCursor* cursor)
|
static void sdl3_set_cursor(PlatformWindow*, PlatformCursor* cursor)
|
||||||
{
|
{
|
||||||
if (cursor == nullptr)
|
if (cursor == nullptr)
|
||||||
SDL_SetCursor(s_default_cursor);
|
SDL_SetCursor(s_default_cursor);
|
||||||
@@ -422,15 +434,19 @@ static void sdl2_set_cursor(PlatformWindow*, PlatformCursor* cursor)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PlatformOps g_platform_ops = {
|
PlatformOps g_platform_ops = {
|
||||||
.initialize = sdl2_initialize,
|
.initialize = sdl3_initialize,
|
||||||
.poll_events = sdl2_poll_events,
|
.poll_events = sdl3_poll_events,
|
||||||
.create_window = sdl2_create_window,
|
.create_window = sdl3_create_window,
|
||||||
.invalidate = sdl2_invalidate,
|
.invalidate = sdl3_invalidate,
|
||||||
.request_resize = sdl2_request_resize,
|
.request_resize = sdl3_request_resize,
|
||||||
.request_fullscreen = sdl2_request_fullscreen,
|
.request_reposition = sdl3_request_reposition,
|
||||||
.create_system_cursor = sdl2_create_system_cursor,
|
.request_fullscreen = sdl3_request_fullscreen,
|
||||||
.create_bitmap_cursor = sdl2_create_bitmap_cursor,
|
.warp_pointer = sdl3_warp_pointer,
|
||||||
.set_cursor = sdl2_set_cursor,
|
.query_pointer = sdl3_query_pointer,
|
||||||
|
.set_pointer_grab = sdl3_set_pointer_grab,
|
||||||
|
.create_system_cursor = sdl3_create_system_cursor,
|
||||||
|
.create_bitmap_cursor = sdl3_create_bitmap_cursor,
|
||||||
|
.set_cursor = sdl3_set_cursor,
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <LibInput/KeyEvent.h>
|
#include <LibInput/KeyEvent.h>
|
||||||
@@ -553,4 +569,4 @@ consteval Keymap::Keymap()
|
|||||||
map[SDL_SCANCODE_KP_ENTER] = keycode_numpad(3, 3);
|
map[SDL_SCANCODE_KP_ENTER] = keycode_numpad(3, 3);
|
||||||
map[SDL_SCANCODE_KP_0] = keycode_numpad(4, 0);
|
map[SDL_SCANCODE_KP_0] = keycode_numpad(4, 0);
|
||||||
map[SDL_SCANCODE_KP_COMMA] = keycode_numpad(4, 1);
|
map[SDL_SCANCODE_KP_COMMA] = keycode_numpad(4, 1);
|
||||||
};
|
};
|
||||||
@@ -120,6 +120,13 @@ static void bananos_request_resize(PlatformWindow* window, uint32_t width, uint3
|
|||||||
banan_window.window->request_resize(width, height);
|
banan_window.window->request_resize(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bananos_request_reposition(PlatformWindow* window, int32_t x, int32_t y)
|
||||||
|
{
|
||||||
|
(void)window;
|
||||||
|
(void)x;
|
||||||
|
(void)y;
|
||||||
|
}
|
||||||
|
|
||||||
static void bananos_invalidate(PlatformWindow* window, const uint32_t* pixels, uint32_t x, uint32_t y, uint32_t width, uint32_t height)
|
static void bananos_invalidate(PlatformWindow* window, const uint32_t* pixels, uint32_t x, uint32_t y, uint32_t width, uint32_t height)
|
||||||
{
|
{
|
||||||
auto& banan_window = *static_cast<BananWindow*>(window);
|
auto& banan_window = *static_cast<BananWindow*>(window);
|
||||||
@@ -134,6 +141,31 @@ static void bananos_invalidate(PlatformWindow* window, const uint32_t* pixels, u
|
|||||||
banan_window.window->invalidate(x, y, width, height);
|
banan_window.window->invalidate(x, y, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bananos_request_fullscreen(PlatformWindow* window, bool fullscreen)
|
||||||
|
{
|
||||||
|
auto& banan_window = *static_cast<BananWindow*>(window);
|
||||||
|
banan_window.window->set_fullscreen(fullscreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bananos_warp_pointer(int32_t x, int32_t y, bool relative)
|
||||||
|
{
|
||||||
|
(void)x;
|
||||||
|
(void)y;
|
||||||
|
(void)relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bananos_query_pointer(int32_t* x, int32_t* y)
|
||||||
|
{
|
||||||
|
(void)x;
|
||||||
|
(void)y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bananos_set_pointer_grab(PlatformWindow* window, bool grabbed)
|
||||||
|
{
|
||||||
|
(void)window;
|
||||||
|
(void)grabbed;
|
||||||
|
}
|
||||||
|
|
||||||
static BAN::ErrorOr<BAN::UniqPtr<PlatformCursor>> bananos_create_system_cursor(SystemCursorType type)
|
static BAN::ErrorOr<BAN::UniqPtr<PlatformCursor>> bananos_create_system_cursor(SystemCursorType type)
|
||||||
{
|
{
|
||||||
(void)type;
|
(void)type;
|
||||||
@@ -169,19 +201,17 @@ static void bananos_set_cursor(PlatformWindow* window, PlatformCursor* cursor)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bananos_request_fullscreen(PlatformWindow* window, bool fullscreen)
|
|
||||||
{
|
|
||||||
auto& banan_window = *static_cast<BananWindow*>(window);
|
|
||||||
banan_window.window->set_fullscreen(fullscreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
PlatformOps g_platform_ops = {
|
PlatformOps g_platform_ops = {
|
||||||
.initialize = bananos_initialize,
|
.initialize = bananos_initialize,
|
||||||
.poll_events = bananos_poll_events,
|
.poll_events = bananos_poll_events,
|
||||||
.create_window = bananos_create_window,
|
.create_window = bananos_create_window,
|
||||||
.invalidate = bananos_invalidate,
|
.invalidate = bananos_invalidate,
|
||||||
.request_resize = bananos_request_resize,
|
.request_resize = bananos_request_resize,
|
||||||
|
.request_reposition = bananos_request_reposition,
|
||||||
.request_fullscreen = bananos_request_fullscreen,
|
.request_fullscreen = bananos_request_fullscreen,
|
||||||
|
.warp_pointer = bananos_warp_pointer,
|
||||||
|
.query_pointer = nullptr, /* bananos_query_pointer */
|
||||||
|
.set_pointer_grab = bananos_set_pointer_grab,
|
||||||
.create_system_cursor = bananos_create_system_cursor,
|
.create_system_cursor = bananos_create_system_cursor,
|
||||||
.create_bitmap_cursor = bananos_create_bitmap_cursor,
|
.create_bitmap_cursor = bananos_create_bitmap_cursor,
|
||||||
.set_cursor = bananos_set_cursor,
|
.set_cursor = bananos_set_cursor,
|
||||||
|
|||||||
@@ -290,6 +290,18 @@ int main()
|
|||||||
window.event_masks.remove(&client_info);
|
window.event_masks.remove(&client_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto it = client_info.objects.begin(); it != client_info.objects.end();)
|
||||||
|
{
|
||||||
|
auto obj_it = g_objects.find(*it);
|
||||||
|
if (obj_it == g_objects.end() || obj_it->value->type != Object::Type::Window)
|
||||||
|
it++;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(void)destroy_window(client_info, *it);
|
||||||
|
it = client_info.objects.begin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto id : client_info.objects)
|
for (auto id : client_info.objects)
|
||||||
{
|
{
|
||||||
auto it = g_objects.find(id);
|
auto it = g_objects.find(id);
|
||||||
@@ -304,14 +316,13 @@ int main()
|
|||||||
case Object::Type::Pixmap:
|
case Object::Type::Pixmap:
|
||||||
case Object::Type::GraphicsContext:
|
case Object::Type::GraphicsContext:
|
||||||
case Object::Type::Font:
|
case Object::Type::Font:
|
||||||
case Object::Type::Window:
|
|
||||||
break;
|
break;
|
||||||
|
case Object::Type::Window:
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
case Object::Type::Extension:
|
case Object::Type::Extension:
|
||||||
{
|
|
||||||
auto& extension = object.object.get<Object::Extension>();
|
auto& extension = object.object.get<Object::Extension>();
|
||||||
extension.destructor(extension);
|
extension.destructor(extension);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_objects.remove(it);
|
g_objects.remove(it);
|
||||||
|
|||||||
Reference in New Issue
Block a user