mirror of
https://github.com/lbonn/rofi
synced 2024-11-26 13:50:27 +00:00
Wayland: Fix incomplete merge/refactor of xcb display
This commit is contained in:
parent
d19e8cfe10
commit
ce950c2ad8
4 changed files with 177 additions and 1830 deletions
|
@ -61,6 +61,7 @@ struct _xcb_stuff {
|
|||
NkBindingsSeat *bindings_seat;
|
||||
gboolean mouse_seen;
|
||||
xcb_window_t focus_revert;
|
||||
char *clipboard;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -41,6 +41,8 @@ typedef struct _xcb_stuff xcb_stuff;
|
|||
*/
|
||||
extern xcb_stuff *xcb;
|
||||
|
||||
void xcb_stuff_set_clipboard(char *data);
|
||||
|
||||
/**
|
||||
* Get the root window.
|
||||
*
|
||||
|
@ -77,9 +79,9 @@ void window_set_atom_prop(xcb_window_t w, xcb_atom_t prop, xcb_atom_t *atoms,
|
|||
|
||||
/** Atoms we want to pre-load */
|
||||
#define EWMH_ATOMS(X) \
|
||||
X(_NET_WM_WINDOW_OPACITY), X(I3_SOCKET_PATH), X(UTF8_STRING), X(STRING), \
|
||||
X(CLIPBOARD), X(WM_WINDOW_ROLE), X(_XROOTPMAP_ID), X(_MOTIF_WM_HINTS), \
|
||||
X(WM_TAKE_FOCUS), X(ESETROOT_PMAP_ID)
|
||||
X(_NET_WM_WINDOW_OPACITY), X(I3_SOCKET_PATH), X(TARGETS), X(UTF8_STRING), \
|
||||
X(STRING), X(CLIPBOARD), X(WM_WINDOW_ROLE), X(_XROOTPMAP_ID), \
|
||||
X(_MOTIF_WM_HINTS), X(WM_TAKE_FOCUS), X(ESETROOT_PMAP_ID)
|
||||
|
||||
/** enumeration of the atoms. */
|
||||
enum { EWMH_ATOMS(ATOM_ENUM), NUM_NETATOMS };
|
||||
|
|
1817
source/xcb.c
1817
source/xcb.c
File diff suppressed because it is too large
Load diff
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* MIT/X11 License
|
||||
* Copyright © 2012 Sean Pringle <sean.pringle@gmail.com>
|
||||
* Copyright © 2013-2021 Qball Cow <qball@gmpclient.org>
|
||||
* Copyright © 2013-2022 Qball Cow <qball@gmpclient.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
|
@ -64,6 +64,9 @@
|
|||
#include "xcb.h"
|
||||
#include <libsn/sn.h>
|
||||
|
||||
#include "mode.h"
|
||||
#include "modes/window.h"
|
||||
|
||||
#include <rofi.h>
|
||||
|
||||
/** Minimal randr preferred for running rofi (1.5) (Major version number) */
|
||||
|
@ -85,7 +88,8 @@ struct _xcb_stuff xcb_int = {.connection = NULL,
|
|||
.screen_nbr = -1,
|
||||
.sndisplay = NULL,
|
||||
.sncontext = NULL,
|
||||
.monitors = NULL};
|
||||
.monitors = NULL,
|
||||
.clipboard = NULL};
|
||||
xcb_stuff *xcb = &xcb_int;
|
||||
|
||||
/**
|
||||
|
@ -101,11 +105,17 @@ static xcb_visualtype_t *root_visual = NULL;
|
|||
xcb_atom_t netatoms[NUM_NETATOMS];
|
||||
const char *netatom_names[] = {EWMH_ATOMS(ATOM_CHAR)};
|
||||
|
||||
/**
|
||||
* Cached X11 cursors.
|
||||
*/
|
||||
xcb_cursor_t cursors[NUM_CURSORS] = {XCB_CURSOR_NONE, XCB_CURSOR_NONE,
|
||||
XCB_CURSOR_NONE};
|
||||
|
||||
/** Mapping between theme name and system name for mouse cursor. */
|
||||
const struct {
|
||||
/** Theme name */
|
||||
const char *css_name;
|
||||
/** System name */
|
||||
const char *traditional_name;
|
||||
} cursor_names[] = {
|
||||
{"default", "left_ptr"}, {"pointer", "hand"}, {"text", "xterm"}};
|
||||
|
@ -418,6 +428,23 @@ static void x11_monitors_free(void) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick function that tries to fix the size (for dpi calculation)
|
||||
* when monitor is rotate. This assumes the density is kinda equal in both X/Y
|
||||
* direction.
|
||||
*/
|
||||
static void x11_workarea_fix_rotation(workarea *w) {
|
||||
double ratio_res = w->w / (double)w->h;
|
||||
double ratio_size = w->mw / (double)w->mh;
|
||||
|
||||
if ((ratio_res < 1.0 && ratio_size > 1.0) ||
|
||||
(ratio_res > 1.0 && ratio_size < 1.0)) {
|
||||
// Oposite ratios, swap them.
|
||||
int nh = w->mw;
|
||||
w->mw = w->mh;
|
||||
w->mh = nh;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Create monitor based on output id
|
||||
*/
|
||||
|
@ -446,6 +473,7 @@ static workarea *x11_get_monitor_from_output(xcb_randr_output_t out) {
|
|||
|
||||
retv->mw = op_reply->mm_width;
|
||||
retv->mh = op_reply->mm_height;
|
||||
x11_workarea_fix_rotation(retv);
|
||||
|
||||
char *tname = (char *)xcb_randr_get_output_info_name(op_reply);
|
||||
int tname_len = xcb_randr_get_output_info_name_length(op_reply);
|
||||
|
@ -496,6 +524,7 @@ x11_get_monitor_from_randr_monitor(xcb_randr_monitor_info_t *mon) {
|
|||
// Physical
|
||||
retv->mw = mon->width_in_millimeters;
|
||||
retv->mh = mon->height_in_millimeters;
|
||||
x11_workarea_fix_rotation(retv);
|
||||
|
||||
// Name
|
||||
retv->name =
|
||||
|
@ -739,6 +768,10 @@ static int monitor_get_dimension(int monitor_id, workarea *mon) {
|
|||
}
|
||||
// find the dimensions of the monitor displaying point x,y
|
||||
static void monitor_dimensions(int x, int y, workarea *mon) {
|
||||
if (mon == NULL) {
|
||||
g_error("%s: mon == NULL", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
memset(mon, 0, sizeof(workarea));
|
||||
mon->w = xcb->screen->width_in_pixels;
|
||||
mon->h = xcb->screen->height_in_pixels;
|
||||
|
@ -777,6 +810,10 @@ static int pointer_get(xcb_window_t root, int *x, int *y) {
|
|||
return FALSE;
|
||||
}
|
||||
static int monitor_active_from_winid(xcb_drawable_t id, workarea *mon) {
|
||||
if (mon == NULL) {
|
||||
g_error("%s: mon == NULL", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
xcb_window_t root = xcb->screen->root;
|
||||
xcb_get_geometry_cookie_t c = xcb_get_geometry(xcb->connection, id);
|
||||
xcb_get_geometry_reply_t *r =
|
||||
|
@ -806,6 +843,10 @@ static int monitor_active_from_id_focused(int mon_id, workarea *mon) {
|
|||
int retv = FALSE;
|
||||
xcb_window_t active_window;
|
||||
xcb_get_property_cookie_t awc;
|
||||
if (mon == NULL) {
|
||||
g_error("%s: mon == NULL", __FUNCTION__);
|
||||
return retv;
|
||||
}
|
||||
awc = xcb_ewmh_get_active_window(&xcb->ewmh, xcb->screen_nbr);
|
||||
if (!xcb_ewmh_get_active_window_reply(&xcb->ewmh, awc, &active_window,
|
||||
NULL)) {
|
||||
|
@ -854,7 +895,9 @@ static int monitor_active_from_id_focused(int mon_id, workarea *mon) {
|
|||
}
|
||||
g_debug("mon pos: %d %d %d-%d", mon->x, mon->y, mon->w, mon->h);
|
||||
} else if (mon_id == -4) {
|
||||
g_debug("Find monitor at location: %d %d", t->dst_x, t->dst_y);
|
||||
monitor_dimensions(t->dst_x, t->dst_y, mon);
|
||||
g_debug("Monitor found pos: %d %d %d-%d", mon->x, mon->y, mon->w, mon->h);
|
||||
retv = TRUE;
|
||||
}
|
||||
free(t);
|
||||
|
@ -869,6 +912,11 @@ static int monitor_active_from_id_focused(int mon_id, workarea *mon) {
|
|||
static int monitor_active_from_id(int mon_id, workarea *mon) {
|
||||
xcb_window_t root = xcb->screen->root;
|
||||
int x, y;
|
||||
if (mon == NULL) {
|
||||
g_error("%s: mon == NULL", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
g_debug("Monitor id: %d", mon_id);
|
||||
// At mouse position.
|
||||
if (mon_id == -3) {
|
||||
if (pointer_get(root, &x, &y)) {
|
||||
|
@ -880,19 +928,27 @@ static int monitor_active_from_id(int mon_id, workarea *mon) {
|
|||
}
|
||||
// Focused monitor
|
||||
else if (mon_id == -1) {
|
||||
g_debug("rofi on current monitor");
|
||||
// Get the current desktop.
|
||||
unsigned int current_desktop = 0;
|
||||
xcb_get_property_cookie_t gcdc;
|
||||
gcdc = xcb_ewmh_get_current_desktop(&xcb->ewmh, xcb->screen_nbr);
|
||||
if (xcb_ewmh_get_current_desktop_reply(&xcb->ewmh, gcdc, ¤t_desktop,
|
||||
NULL)) {
|
||||
g_debug("Found current desktop: %u", current_desktop);
|
||||
xcb_get_property_cookie_t c =
|
||||
xcb_ewmh_get_desktop_viewport(&xcb->ewmh, xcb->screen_nbr);
|
||||
xcb_ewmh_get_desktop_viewport_reply_t vp;
|
||||
if (xcb_ewmh_get_desktop_viewport_reply(&xcb->ewmh, c, &vp, NULL)) {
|
||||
g_debug("Found %d number of desktops", vp.desktop_viewport_len);
|
||||
if (current_desktop < vp.desktop_viewport_len) {
|
||||
g_debug("Found viewport for desktop: %d %d",
|
||||
vp.desktop_viewport[current_desktop].x,
|
||||
vp.desktop_viewport[current_desktop].y);
|
||||
monitor_dimensions(vp.desktop_viewport[current_desktop].x,
|
||||
vp.desktop_viewport[current_desktop].y, mon);
|
||||
g_debug("Found monitor @: %d %d %dx%d", mon->x, mon->y, mon->w,
|
||||
mon->h);
|
||||
xcb_ewmh_get_desktop_viewport_reply_wipe(&vp);
|
||||
return TRUE;
|
||||
} else {
|
||||
|
@ -930,20 +986,39 @@ static int monitor_active_from_id(int mon_id, workarea *mon) {
|
|||
|
||||
// determine which monitor holds the active window, or failing that the mouse
|
||||
// pointer
|
||||
gboolean mon_set = FALSE;
|
||||
workarea mon_cache = {
|
||||
0,
|
||||
};
|
||||
static int xcb_display_monitor_active(workarea *mon) {
|
||||
if (mon == NULL) {
|
||||
g_error("%s: mon == NULL", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
g_debug("Monitor active");
|
||||
if (mon_set) {
|
||||
*mon = mon_cache;
|
||||
return TRUE;
|
||||
}
|
||||
if (config.monitor != NULL) {
|
||||
g_debug("Monitor lookup by name : %s", config.monitor);
|
||||
for (workarea *iter = xcb->monitors; iter; iter = iter->next) {
|
||||
if (g_strcmp0(config.monitor, iter->name) == 0) {
|
||||
*mon = *iter;
|
||||
mon_cache = *mon;
|
||||
mon_set = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
g_debug("Monitor lookup by name failed: %s", config.monitor);
|
||||
// Grab primary.
|
||||
if (g_strcmp0(config.monitor, "primary") == 0) {
|
||||
for (workarea *iter = xcb->monitors; iter; iter = iter->next) {
|
||||
if (iter->primary) {
|
||||
*mon = *iter;
|
||||
mon_cache = *mon;
|
||||
mon_set = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -953,6 +1028,8 @@ static int xcb_display_monitor_active(workarea *mon) {
|
|||
xcb_drawable_t win = g_ascii_strtoll(config.monitor + 4, &end, 0);
|
||||
if (end != config.monitor) {
|
||||
if (monitor_active_from_winid(win, mon)) {
|
||||
mon_cache = *mon;
|
||||
mon_set = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -964,16 +1041,23 @@ static int xcb_display_monitor_active(workarea *mon) {
|
|||
if (end != config.monitor) {
|
||||
if (mon_id >= 0) {
|
||||
if (monitor_get_dimension(mon_id, mon)) {
|
||||
mon_cache = *mon;
|
||||
mon_set = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
g_warning("Failed to find selected monitor.");
|
||||
} else {
|
||||
return monitor_active_from_id(mon_id, mon);
|
||||
int val = monitor_active_from_id(mon_id, mon);
|
||||
mon_cache = *mon;
|
||||
mon_set = TRUE;
|
||||
return val;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fallback.
|
||||
monitor_dimensions(0, 0, mon);
|
||||
mon_cache = *mon;
|
||||
mon_set = TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -1079,6 +1163,26 @@ static void main_loop_x11_event_handler_view(xcb_generic_event_t *event) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case XCB_DESTROY_NOTIFY: {
|
||||
xcb_window_t win = ((xcb_destroy_notify_event_t *)event)->window;
|
||||
if (win != rofi_view_get_window()) {
|
||||
#ifdef WINDOW_MODE
|
||||
window_client_handle_signal(win, FALSE);
|
||||
#endif
|
||||
} else {
|
||||
g_main_loop_quit(xcb->main_loop);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XCB_CREATE_NOTIFY: {
|
||||
xcb_window_t win = ((xcb_create_notify_event_t *)event)->window;
|
||||
if (win != rofi_view_get_window()) {
|
||||
#ifdef WINDOW_MODE
|
||||
window_client_handle_signal(win, TRUE);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XCB_EXPOSE:
|
||||
rofi_view_frame_callback();
|
||||
break;
|
||||
|
@ -1113,6 +1217,52 @@ static void main_loop_x11_event_handler_view(xcb_generic_event_t *event) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case XCB_SELECTION_CLEAR: {
|
||||
g_debug("Selection Clear.");
|
||||
xcb_stuff_set_clipboard(NULL);
|
||||
} break;
|
||||
case XCB_SELECTION_REQUEST: {
|
||||
g_debug("Selection Request.");
|
||||
xcb_selection_request_event_t *req = (xcb_selection_request_event_t *)event;
|
||||
if (req->selection == netatoms[CLIPBOARD]) {
|
||||
xcb_atom_t targets[2];
|
||||
xcb_selection_notify_event_t selection_notify = {
|
||||
.response_type = XCB_SELECTION_NOTIFY,
|
||||
.sequence = 0,
|
||||
.time = req->time,
|
||||
.requestor = req->requestor,
|
||||
.selection = req->selection,
|
||||
.target = req->target,
|
||||
.property = XCB_ATOM_NONE,
|
||||
};
|
||||
// If no clipboard, we return NONE.
|
||||
if (xcb->clipboard) {
|
||||
// Request for UTF-8
|
||||
if (req->target == netatoms[UTF8_STRING]) {
|
||||
g_debug("Selection Request UTF-8.");
|
||||
xcb_change_property(xcb->connection, XCB_PROP_MODE_REPLACE,
|
||||
req->requestor, req->property,
|
||||
netatoms[UTF8_STRING], 8,
|
||||
strlen(xcb->clipboard) + 1, xcb->clipboard);
|
||||
selection_notify.property = req->property;
|
||||
} else if (req->target == netatoms[TARGETS]) {
|
||||
g_debug("Selection Request Targets.");
|
||||
// We currently only support UTF8 from clipboard. So indicate this.
|
||||
targets[0] = netatoms[UTF8_STRING];
|
||||
xcb_change_property(xcb->connection, XCB_PROP_MODE_REPLACE,
|
||||
req->requestor, req->property, XCB_ATOM_ATOM, 32,
|
||||
1, targets);
|
||||
selection_notify.property = req->property;
|
||||
}
|
||||
}
|
||||
|
||||
xcb_send_event(xcb->connection,
|
||||
0, // propagate
|
||||
req->requestor, XCB_EVENT_MASK_NO_EVENT,
|
||||
(const char *)&selection_notify);
|
||||
xcb_flush(xcb->connection);
|
||||
}
|
||||
} break;
|
||||
case XCB_BUTTON_RELEASE: {
|
||||
xcb_button_release_event_t *bre = (xcb_button_release_event_t *)event;
|
||||
NkBindingsMouseButton button;
|
||||
|
@ -1154,11 +1304,17 @@ static void main_loop_x11_event_handler_view(xcb_generic_event_t *event) {
|
|||
gchar *text;
|
||||
|
||||
xcb->last_timestamp = xkpe->time;
|
||||
text = nk_bindings_seat_handle_key_with_modmask(
|
||||
xcb->bindings_seat, NULL, xkpe->state, xkpe->detail,
|
||||
NK_BINDINGS_KEY_STATE_PRESS);
|
||||
if (config.xserver_i300_workaround) {
|
||||
text = nk_bindings_seat_handle_key_with_modmask(
|
||||
xcb->bindings_seat, NULL, xkpe->state, xkpe->detail,
|
||||
NK_BINDINGS_KEY_STATE_PRESS);
|
||||
} else {
|
||||
text = nk_bindings_seat_handle_key(xcb->bindings_seat, NULL, xkpe->detail,
|
||||
NK_BINDINGS_KEY_STATE_PRESS);
|
||||
}
|
||||
if (text != NULL) {
|
||||
rofi_view_handle_text(state, text);
|
||||
g_free(text);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1183,11 +1339,12 @@ static gboolean main_loop_x11_event_handler(xcb_generic_event_t *ev,
|
|||
g_warning("The XCB connection to X server had a fatal error: %d", status);
|
||||
g_main_loop_quit(xcb->main_loop);
|
||||
return G_SOURCE_REMOVE;
|
||||
} else {
|
||||
g_warning("main_loop_x11_event_handler: ev == NULL, status == %d",
|
||||
status);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
// DD: it seems this handler often gets dispatched while the queue in GWater
|
||||
// is empty. resulting in a NULL for ev. This seems not an error.
|
||||
// g_warning("main_loop_x11_event_handler: ev == NULL, status == %d",
|
||||
// status);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
uint8_t type = ev->response_type & ~0x80;
|
||||
if (type == xcb->xkb.first_event) {
|
||||
|
@ -1700,6 +1857,10 @@ void x11_set_cursor(xcb_window_t window, X11CursorType type) {
|
|||
xcb_change_window_attributes(xcb->connection, window, XCB_CW_CURSOR,
|
||||
&(cursors[type]));
|
||||
}
|
||||
void xcb_stuff_set_clipboard(char *data) {
|
||||
g_free(xcb->clipboard);
|
||||
xcb->clipboard = data;
|
||||
}
|
||||
|
||||
static void xcb_display_set_input_focus(guint w) {
|
||||
if (config.steal_focus != TRUE) {
|
||||
|
|
Loading…
Reference in a new issue