diff --git a/src/wine-host/editor.cpp b/src/wine-host/editor.cpp index 185d5e62..0fd45a0c 100644 --- a/src/wine-host/editor.cpp +++ b/src/wine-host/editor.cpp @@ -1,10 +1,23 @@ #include "editor.h" +constexpr char xembed_info_proeprty[] = "_XEMBED_INFO"; + ATOM register_window_class(std::string window_class_name); Editor::Editor(std::string window_class_name) : window_class(register_window_class(window_class_name)), - x11_connection(xcb_connect(nullptr, nullptr), &xcb_disconnect) {} + x11_connection(xcb_connect(nullptr, nullptr), &xcb_disconnect) { + // We need a bunch of property atoms for the XEmbed protocol + xcb_generic_error_t* err; + + const auto xembed_info_cookie = + xcb_intern_atom(x11_connection.get(), 0, strlen(xembed_info_proeprty), + xembed_info_proeprty); + + xcb_xembed_info = + xcb_intern_atom_reply(x11_connection.get(), xembed_info_cookie, &err) + ->atom; +} HWND Editor::open() { // Create a window without any decoratiosn for easy embedding. The @@ -49,14 +62,23 @@ bool Editor::embed_into(const size_t parent_window_handle) { return false; } + // This follows the embedding procedure specified in the XEmbed sped: + // https://specifications.freedesktop.org/xembed-spec/xembed-spec-latest.html + // under 'Embedding life cycle + // Sadly there's doesn't seem to be any implementation of this available as + // a library const size_t child_window_handle = get_x11_handle().value(); - // TODO: Reparenting works, but the Wine window is not updating so that - // might cause it to look like it doesn't work xcb_reparent_window(x11_connection.get(), child_window_handle, parent_window_handle, 0, 0); - // TODO: Is this needed? + // This tells the WM that the parent window embedding and mapping/uumapping + // a child window. Requires the PROPERTY_NOTIFY event. + std::array xembed_info_values{0, 1}; + xcb_change_property(x11_connection.get(), XCB_PROP_MODE_REPLACE, + parent_window_handle, xcb_xembed_info, xcb_xembed_info, + 32, 2, xembed_info_values.data()); + const int parent_events = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_STRUCTURE_NOTIFY; @@ -69,14 +91,16 @@ bool Editor::embed_into(const size_t parent_window_handle) { xcb_change_window_attributes(x11_connection.get(), child_window_handle, XCB_CW_EVENT_MASK, &child_events); + // TODO: Send XEMBED_EMBEDDED_NOTIFY XEMBED_FOCUS_IN, XEMBED_WINDOW_ACTIVATE + // and XEMBED_MODALITY_ON from the parent window Before or after + // embedding? + // TODO: Is this map needed? xcb_map_window(x11_connection.get(), child_window_handle); xcb_flush(x11_connection.get()); - ShowWindow(win32_handle->get(), SW_SHOWNORMAL); - // TODO: We should just immediatly resize the window to the right size - // isntead - UpdateWindow(win32_handle->get()); + // TODO: Should this be done before reparenting and mapping? + ShowWindow(win32_handle->get(), SW_SHOW); return true; } diff --git a/src/wine-host/editor.h b/src/wine-host/editor.h index b9fb6d48..6e7f32ad 100644 --- a/src/wine-host/editor.h +++ b/src/wine-host/editor.h @@ -84,4 +84,5 @@ class Editor { win32_handle; std::unique_ptr x11_connection; + xcb_atom_t xcb_xembed_info; };