aboutsummaryrefslogtreecommitdiff
path: root/sway
diff options
context:
space:
mode:
Diffstat (limited to 'sway')
-rw-r--r--sway/commands.c1
-rw-r--r--sway/commands/hide_cursor.c33
-rw-r--r--sway/config.c2
-rw-r--r--sway/input/cursor.c45
-rw-r--r--sway/meson.build1
-rw-r--r--sway/sway.5.scd6
6 files changed, 81 insertions, 7 deletions
diff --git a/sway/commands.c b/sway/commands.c
index f6d1cc3e..eda29c65 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -86,6 +86,7 @@ static struct cmd_handler handlers[] = {
{ "force_focus_wrapping", cmd_force_focus_wrapping },
{ "fullscreen", cmd_fullscreen },
{ "gaps", cmd_gaps },
+ { "hide_cursor", cmd_hide_cursor },
{ "hide_edge_borders", cmd_hide_edge_borders },
{ "include", cmd_include },
{ "input", cmd_input },
diff --git a/sway/commands/hide_cursor.c b/sway/commands/hide_cursor.c
new file mode 100644
index 00000000..3778fcff
--- /dev/null
+++ b/sway/commands/hide_cursor.c
@@ -0,0 +1,33 @@
+#define _POSIX_C_SOURCE 200809L
+#include <string.h>
+#include "sway/commands.h"
+#include "sway/config.h"
+#include "sway/input/cursor.h"
+#include "sway/input/seat.h"
+#include "stringop.h"
+
+struct cmd_results *cmd_hide_cursor(int argc, char **argv) {
+ struct cmd_results *error = NULL;
+ if ((error = checkarg(argc, "hide_cursor", EXPECTED_EQUAL_TO, 1))) {
+ return error;
+ }
+
+ char *end;
+ int timeout = strtol(argv[0], &end, 10);
+ if (*end) {
+ return cmd_results_new(CMD_INVALID, "hide_cursor",
+ "Expected an integer timeout");
+ }
+ if (timeout < 100 && timeout != 0) {
+ timeout = 100;
+ }
+ config->hide_cursor_timeout = timeout;
+
+ struct sway_seat *seat;
+ wl_list_for_each(seat, &server.input->seats, link) {
+ wl_event_source_timer_update(seat->cursor->hide_source,
+ config->hide_cursor_timeout);
+ }
+
+ return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+}
diff --git a/sway/config.c b/sway/config.c
index d4b7d466..bb18c739 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -257,6 +257,8 @@ static void config_defaults(struct sway_config *config) {
config->hide_edge_borders = E_NONE;
config->saved_edge_borders = E_NONE;
+ config->hide_cursor_timeout = 0;
+
// border colors
set_color(config->border_colors.focused.border, 0x4C7899);
set_color(config->border_colors.focused.background, 0x285577);
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 444fe81d..53ff3a22 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -590,6 +590,23 @@ void cursor_rebase(struct sway_cursor *cursor) {
cursor_do_rebase(cursor, time_msec, cursor->previous.node, surface, sx, sy);
}
+static int hide_notify(void *data) {
+ struct sway_cursor *cursor = data;
+ wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0);
+ cursor->hidden = true;
+ return 1;
+}
+
+static void handle_activity(struct sway_cursor *cursor) {
+ wl_event_source_timer_update(cursor->hide_source,
+ config->hide_cursor_timeout);
+ wlr_idle_notify_activity(server.idle, cursor->seat->wlr_seat);
+ if (cursor->hidden) {
+ cursor->hidden = false;
+ cursor_set_image(cursor, NULL, cursor->image_client);
+ }
+}
+
void cursor_send_pointer_motion(struct sway_cursor *cursor,
uint32_t time_msec) {
if (time_msec == 0) {
@@ -680,11 +697,11 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor,
static void handle_cursor_motion(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of(listener, cursor, motion);
- wlr_idle_notify_activity(server.idle, cursor->seat->wlr_seat);
struct wlr_event_pointer_motion *event = data;
wlr_cursor_move(cursor->cursor, event->device,
event->delta_x, event->delta_y);
cursor_send_pointer_motion(cursor, event->time_msec);
+ handle_activity(cursor);
transaction_commit_dirty();
}
@@ -692,10 +709,10 @@ static void handle_cursor_motion_absolute(
struct wl_listener *listener, void *data) {
struct sway_cursor *cursor =
wl_container_of(listener, cursor, motion_absolute);
- wlr_idle_notify_activity(server.idle, cursor->seat->wlr_seat);
struct wlr_event_pointer_motion_absolute *event = data;
wlr_cursor_warp_absolute(cursor->cursor, event->device, event->x, event->y);
cursor_send_pointer_motion(cursor, event->time_msec);
+ handle_activity(cursor);
transaction_commit_dirty();
}
@@ -976,10 +993,10 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
static void handle_cursor_button(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of(listener, cursor, button);
- wlr_idle_notify_activity(server.idle, cursor->seat->wlr_seat);
struct wlr_event_pointer_button *event = data;
dispatch_cursor_button(cursor, event->device,
event->time_msec, event->button, event->state);
+ handle_activity(cursor);
transaction_commit_dirty();
}
@@ -1087,9 +1104,9 @@ static void dispatch_cursor_axis(struct sway_cursor *cursor,
static void handle_cursor_axis(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of(listener, cursor, axis);
- wlr_idle_notify_activity(server.idle, cursor->seat->wlr_seat);
struct wlr_event_pointer_axis *event = data;
dispatch_cursor_axis(cursor, event);
+ handle_activity(cursor);
transaction_commit_dirty();
}
@@ -1280,10 +1297,12 @@ static void handle_request_set_cursor(struct wl_listener *listener,
return;
}
- wlr_cursor_set_surface(cursor->cursor, event->surface, event->hotspot_x,
- event->hotspot_y);
cursor->image = NULL;
cursor->image_client = focused_client;
+ cursor->image_surface = event->surface;
+ cursor->hotspot_x = event->hotspot_x;
+ cursor->hotspot_y = event->hotspot_y;
+ cursor_set_image(cursor, NULL, cursor->image_client);
}
void cursor_set_image(struct sway_cursor *cursor, const char *image,
@@ -1291,9 +1310,16 @@ void cursor_set_image(struct sway_cursor *cursor, const char *image,
if (!(cursor->seat->wlr_seat->capabilities & WL_SEAT_CAPABILITY_POINTER)) {
return;
}
- if (!image) {
+ if (cursor->hidden) {
+ return;
+ }
+ if (!image && cursor->image_surface) {
+ wlr_cursor_set_surface(cursor->cursor, cursor->image_surface,
+ cursor->hotspot_x, cursor->hotspot_y);
+ } else if (!image) {
wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0);
} else if (!cursor->image || strcmp(cursor->image, image) != 0) {
+ cursor->image_surface = NULL;
wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, image,
cursor->cursor);
}
@@ -1306,6 +1332,8 @@ void sway_cursor_destroy(struct sway_cursor *cursor) {
return;
}
+ wl_event_source_remove(cursor->hide_source);
+
wlr_xcursor_manager_destroy(cursor->xcursor_manager);
wlr_cursor_destroy(cursor->cursor);
free(cursor);
@@ -1329,6 +1357,9 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) {
cursor->seat = seat;
wlr_cursor_attach_output_layout(wlr_cursor, root->output_layout);
+ cursor->hide_source = wl_event_loop_add_timer(server.wl_event_loop,
+ hide_notify, cursor);
+
// input events
wl_signal_add(&wlr_cursor->events.motion, &cursor->motion);
cursor->motion.notify = handle_cursor_motion;
diff --git a/sway/meson.build b/sway/meson.build
index 2f977fd2..48ce6b45 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -56,6 +56,7 @@ sway_sources = files(
'commands/force_focus_wrapping.c',
'commands/fullscreen.c',
'commands/gaps.c',
+ 'commands/hide_cursor.c',
'commands/hide_edge_borders.c',
'commands/kill.c',
'commands/mark.c',
diff --git a/sway/sway.5.scd b/sway/sway.5.scd
index e6abef56..2befcfac 100644
--- a/sway/sway.5.scd
+++ b/sway/sway.5.scd
@@ -477,6 +477,12 @@ The default colors are:
This affects new workspaces only, and is used when the workspace doesn't
have its own gaps settings (see: workspace <ws> gaps ...).
+*hide\_cursor* <timeout>
+ Hides the cursor image after the specified _timeout_ (in milliseconds)
+ has elapsed with no activity on that cursor. A timeout of 0 (default)
+ disables hiding the cursor. The minimal timeout is 100 and any value less
+ than that (aside from 0), will be increased to 100.
+
*hide\_edge\_borders* none|vertical|horizontal|both|smart|smart\_no\_gaps
Hides window borders adjacent to the screen edges. Default is _none_.