mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-09 20:29:10 +02:00
Add a function for fetching X11 atoms by name
This commit is contained in:
+30
-37
@@ -65,7 +65,7 @@ constexpr char active_window_property_name[] = "_NET_ACTIVE_WINDOW";
|
|||||||
* drag-and-drop. If the `editor_force_dnd` option is enabled we'll remove this
|
* drag-and-drop. If the `editor_force_dnd` option is enabled we'll remove this
|
||||||
* property from `topmost_window` to work around a bug in REAPER.
|
* property from `topmost_window` to work around a bug in REAPER.
|
||||||
*/
|
*/
|
||||||
constexpr char x_dnd_aware_property_name[] = "XdndAware";
|
constexpr char xdnd_aware_property_name[] = "XdndAware";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client message name for XEmbed messages. See
|
* Client message name for XEmbed messages. See
|
||||||
@@ -241,21 +241,12 @@ Editor::Editor(MainContext& main_context,
|
|||||||
wine_window(get_x11_handle(win32_window.handle)),
|
wine_window(get_x11_handle(win32_window.handle)),
|
||||||
topmost_window(
|
topmost_window(
|
||||||
find_ancestor_windows(*x11_connection, parent_window).back()) {
|
find_ancestor_windows(*x11_connection, parent_window).back()) {
|
||||||
xcb_generic_error_t* error;
|
|
||||||
|
|
||||||
// Used for input focus grabbing to only grab focus when the window is
|
// Used for input focus grabbing to only grab focus when the window is
|
||||||
// active.
|
// active. In case the atom does not exist or the WM does not support this
|
||||||
xcb_intern_atom_cookie_t atom_cookie = xcb_intern_atom(
|
// hint, we'll print a warning and fall back to grabbing focus when the user
|
||||||
x11_connection.get(), true, strlen(active_window_property_name),
|
|
||||||
active_window_property_name);
|
|
||||||
std::unique_ptr<xcb_intern_atom_reply_t> atom_reply(
|
|
||||||
xcb_intern_atom_reply(x11_connection.get(), atom_cookie, &error));
|
|
||||||
THROW_X11_ERROR(error);
|
|
||||||
|
|
||||||
// In case the atom does not exist or the WM does not support this hint,
|
|
||||||
// we'll print a warning and fall back to grabbing focus when the user
|
|
||||||
// clicks on the window (which should trigger a `WM_PARENTNOTIFY`).
|
// clicks on the window (which should trigger a `WM_PARENTNOTIFY`).
|
||||||
active_window_property = atom_reply->atom;
|
active_window_property =
|
||||||
|
get_atom_by_name(*x11_connection, active_window_property_name);
|
||||||
if (!supports_ewmh_active_window()) {
|
if (!supports_ewmh_active_window()) {
|
||||||
std::cerr << "WARNING: The current window manager does not support the"
|
std::cerr << "WARNING: The current window manager does not support the"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
@@ -271,29 +262,19 @@ Editor::Editor(MainContext& main_context,
|
|||||||
// `Configuration::editor_force_dnd` and the option description in the
|
// `Configuration::editor_force_dnd` and the option description in the
|
||||||
// readme for more information.
|
// readme for more information.
|
||||||
if (config.editor_force_dnd) {
|
if (config.editor_force_dnd) {
|
||||||
atom_cookie = xcb_intern_atom(x11_connection.get(), true,
|
const xcb_atom_t xcb_xdnd_aware_property =
|
||||||
strlen(x_dnd_aware_property_name),
|
get_atom_by_name(*x11_connection, xdnd_aware_property_name);
|
||||||
x_dnd_aware_property_name);
|
|
||||||
atom_reply.reset(
|
|
||||||
xcb_intern_atom_reply(x11_connection.get(), atom_cookie, &error));
|
|
||||||
THROW_X11_ERROR(error);
|
|
||||||
|
|
||||||
for (const xcb_window_t& window :
|
for (const xcb_window_t& window :
|
||||||
find_ancestor_windows(*x11_connection, parent_window)) {
|
find_ancestor_windows(*x11_connection, parent_window)) {
|
||||||
xcb_delete_property(x11_connection.get(), window, atom_reply->atom);
|
xcb_delete_property(x11_connection.get(), window,
|
||||||
|
xcb_xdnd_aware_property);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// When using XEmbed we'll need the atoms for the corresponding properties
|
// When using XEmbed we'll need the atoms for the corresponding properties
|
||||||
if (use_xembed) {
|
if (use_xembed) {
|
||||||
atom_cookie =
|
xcb_xembed_message =
|
||||||
xcb_intern_atom(x11_connection.get(), true,
|
get_atom_by_name(*x11_connection, xembed_message_name);
|
||||||
strlen(xembed_message_name), xembed_message_name);
|
|
||||||
atom_reply.reset(
|
|
||||||
xcb_intern_atom_reply(x11_connection.get(), atom_cookie, &error));
|
|
||||||
THROW_X11_ERROR(error);
|
|
||||||
|
|
||||||
xcb_xembed_message = atom_reply->atom;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// When not using XEmbed, Wine will interpret any local coordinates as
|
// When not using XEmbed, Wine will interpret any local coordinates as
|
||||||
@@ -498,7 +479,7 @@ void Editor::fix_local_coordinates() const {
|
|||||||
// inside directly inside of the dialog, and Waveform then moves the
|
// inside directly inside of the dialog, and Waveform then moves the
|
||||||
// window 27 pixels down. That's why we cannot use `parent_window`
|
// window 27 pixels down. That's why we cannot use `parent_window`
|
||||||
// here.
|
// here.
|
||||||
xcb_generic_error_t* error;
|
xcb_generic_error_t* error = nullptr;
|
||||||
const xcb_translate_coordinates_cookie_t translate_cookie =
|
const xcb_translate_coordinates_cookie_t translate_cookie =
|
||||||
xcb_translate_coordinates(x11_connection.get(), wine_window, root, 0,
|
xcb_translate_coordinates(x11_connection.get(), wine_window, root, 0,
|
||||||
0);
|
0);
|
||||||
@@ -530,7 +511,7 @@ void Editor::fix_local_coordinates() const {
|
|||||||
void Editor::set_input_focus(bool grab) const {
|
void Editor::set_input_focus(bool grab) const {
|
||||||
const xcb_window_t focus_target = grab ? parent_window : topmost_window;
|
const xcb_window_t focus_target = grab ? parent_window : topmost_window;
|
||||||
|
|
||||||
xcb_generic_error_t* error;
|
xcb_generic_error_t* error = nullptr;
|
||||||
const xcb_get_input_focus_cookie_t focus_cookie =
|
const xcb_get_input_focus_cookie_t focus_cookie =
|
||||||
xcb_get_input_focus(x11_connection.get());
|
xcb_get_input_focus(x11_connection.get());
|
||||||
const std::unique_ptr<xcb_get_input_focus_reply_t> focus_reply(
|
const std::unique_ptr<xcb_get_input_focus_reply_t> focus_reply(
|
||||||
@@ -590,7 +571,7 @@ bool Editor::is_wine_window_active() const {
|
|||||||
const xcb_window_t root_window =
|
const xcb_window_t root_window =
|
||||||
get_root_window(*x11_connection, wine_window);
|
get_root_window(*x11_connection, wine_window);
|
||||||
|
|
||||||
xcb_generic_error_t* error;
|
xcb_generic_error_t* error = nullptr;
|
||||||
const xcb_get_property_cookie_t property_cookie =
|
const xcb_get_property_cookie_t property_cookie =
|
||||||
xcb_get_property(x11_connection.get(), false, root_window,
|
xcb_get_property(x11_connection.get(), false, root_window,
|
||||||
active_window_property, XCB_ATOM_WINDOW, 0, 1);
|
active_window_property, XCB_ATOM_WINDOW, 0, 1);
|
||||||
@@ -623,7 +604,7 @@ bool Editor::supports_ewmh_active_window() const {
|
|||||||
// If the `_NET_ACTIVE_WINDOW` property does not exist on the root window,
|
// If the `_NET_ACTIVE_WINDOW` property does not exist on the root window,
|
||||||
// the returned property type will be `XCB_ATOM_NONE` as specified in the
|
// the returned property type will be `XCB_ATOM_NONE` as specified in the
|
||||||
// X11 manual
|
// X11 manual
|
||||||
xcb_generic_error_t* error;
|
xcb_generic_error_t* error = nullptr;
|
||||||
const xcb_get_property_cookie_t property_cookie =
|
const xcb_get_property_cookie_t property_cookie =
|
||||||
xcb_get_property(x11_connection.get(), false, root_window,
|
xcb_get_property(x11_connection.get(), false, root_window,
|
||||||
active_window_property, XCB_ATOM_WINDOW, 0, 1);
|
active_window_property, XCB_ATOM_WINDOW, 0, 1);
|
||||||
@@ -772,7 +753,7 @@ boost::container::small_vector<xcb_window_t, 8> find_ancestor_windows(
|
|||||||
xcb_connection_t& x11_connection,
|
xcb_connection_t& x11_connection,
|
||||||
xcb_window_t starting_at) {
|
xcb_window_t starting_at) {
|
||||||
xcb_window_t current_window = starting_at;
|
xcb_window_t current_window = starting_at;
|
||||||
xcb_generic_error_t* error;
|
xcb_generic_error_t* error = nullptr;
|
||||||
xcb_query_tree_cookie_t query_cookie =
|
xcb_query_tree_cookie_t query_cookie =
|
||||||
xcb_query_tree(&x11_connection, starting_at);
|
xcb_query_tree(&x11_connection, starting_at);
|
||||||
std::unique_ptr<xcb_query_tree_reply_t> query_reply(
|
std::unique_ptr<xcb_query_tree_reply_t> query_reply(
|
||||||
@@ -798,7 +779,7 @@ boost::container::small_vector<xcb_window_t, 8> find_ancestor_windows(
|
|||||||
bool is_child_window_or_same(xcb_connection_t& x11_connection,
|
bool is_child_window_or_same(xcb_connection_t& x11_connection,
|
||||||
xcb_window_t child,
|
xcb_window_t child,
|
||||||
xcb_window_t parent) {
|
xcb_window_t parent) {
|
||||||
xcb_generic_error_t* error;
|
xcb_generic_error_t* error = nullptr;
|
||||||
xcb_query_tree_cookie_t query_cookie =
|
xcb_query_tree_cookie_t query_cookie =
|
||||||
xcb_query_tree(&x11_connection, child);
|
xcb_query_tree(&x11_connection, child);
|
||||||
std::unique_ptr<xcb_query_tree_reply_t> query_reply(
|
std::unique_ptr<xcb_query_tree_reply_t> query_reply(
|
||||||
@@ -822,6 +803,18 @@ bool is_child_window_or_same(xcb_connection_t& x11_connection,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xcb_atom_t get_atom_by_name(xcb_connection_t& x11_connection,
|
||||||
|
const char* atom_name) {
|
||||||
|
xcb_generic_error_t* error = nullptr;
|
||||||
|
xcb_intern_atom_cookie_t atom_cookie =
|
||||||
|
xcb_intern_atom(&x11_connection, true, strlen(atom_name), atom_name);
|
||||||
|
std::unique_ptr<xcb_intern_atom_reply_t> atom_reply(
|
||||||
|
xcb_intern_atom_reply(&x11_connection, atom_cookie, &error));
|
||||||
|
THROW_X11_ERROR(error);
|
||||||
|
|
||||||
|
return atom_reply->atom;
|
||||||
|
}
|
||||||
|
|
||||||
Size get_maximum_screen_dimensions(xcb_connection_t& x11_connection) noexcept {
|
Size get_maximum_screen_dimensions(xcb_connection_t& x11_connection) noexcept {
|
||||||
xcb_screen_iterator_t iter =
|
xcb_screen_iterator_t iter =
|
||||||
xcb_setup_roots_iterator(xcb_get_setup(&x11_connection));
|
xcb_setup_roots_iterator(xcb_get_setup(&x11_connection));
|
||||||
@@ -845,7 +838,7 @@ Size get_maximum_screen_dimensions(xcb_connection_t& x11_connection) noexcept {
|
|||||||
|
|
||||||
xcb_window_t get_root_window(xcb_connection_t& x11_connection,
|
xcb_window_t get_root_window(xcb_connection_t& x11_connection,
|
||||||
xcb_window_t window) {
|
xcb_window_t window) {
|
||||||
xcb_generic_error_t* error;
|
xcb_generic_error_t* error = nullptr;
|
||||||
const xcb_query_tree_cookie_t query_cookie =
|
const xcb_query_tree_cookie_t query_cookie =
|
||||||
xcb_query_tree(&x11_connection, window);
|
xcb_query_tree(&x11_connection, window);
|
||||||
std::unique_ptr<xcb_query_tree_reply_t> query_reply(
|
std::unique_ptr<xcb_query_tree_reply_t> query_reply(
|
||||||
|
|||||||
@@ -44,6 +44,16 @@
|
|||||||
*/
|
*/
|
||||||
constexpr int max_win32_messages [[maybe_unused]] = 20;
|
constexpr int max_win32_messages [[maybe_unused]] = 20;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the atom with the specified name. May throw when
|
||||||
|
* `xcb_intern_atom_reply()` returns an error. Returns `XCB_ATOM_NONE` when the
|
||||||
|
* atom doesn't exist. We define this here because we'll also need to fetch a
|
||||||
|
* whole bunch of atoms for the We define this here because we'll also need to
|
||||||
|
* fetch a whole bunch of atoms for the XDND protocol in `xdnd-proxy.cpp`.
|
||||||
|
*/
|
||||||
|
xcb_atom_t get_atom_by_name(xcb_connection_t& x11_connection,
|
||||||
|
const char* atom_name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to store the maximum width and height of a screen.
|
* Used to store the maximum width and height of a screen.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user