summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sway/config.h3
-rw-r--r--include/sway/input/cursor.h8
-rw-r--r--sway/commands/bind.c130
-rw-r--r--sway/commands/move.c2
-rw-r--r--sway/commands/seat/cursor.c4
-rw-r--r--sway/config.c4
-rw-r--r--sway/input/cursor.c77
-rw-r--r--sway/input/seat.c4
-rw-r--r--sway/ipc-server.c12
-rw-r--r--sway/sway.5.scd2
-rw-r--r--sway/tree/output.c2
-rw-r--r--swaybar/input.c4
-rw-r--r--swaybar/render.c86
13 files changed, 212 insertions, 126 deletions
diff --git a/include/sway/config.h b/include/sway/config.h
index ebf16e6a..29c21afe 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -27,7 +27,8 @@ struct sway_variable {
27enum binding_input_type { 27enum binding_input_type {
28 BINDING_KEYCODE, 28 BINDING_KEYCODE,
29 BINDING_KEYSYM, 29 BINDING_KEYSYM,
30 BINDING_MOUSE, 30 BINDING_MOUSECODE,
31 BINDING_MOUSESYM,
31}; 32};
32 33
33enum binding_flags { 34enum binding_flags {
diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h
index 22e278b0..4636bf6b 100644
--- a/include/sway/input/cursor.h
+++ b/include/sway/input/cursor.h
@@ -86,4 +86,12 @@ void cursor_warp_to_container(struct sway_cursor *cursor,
86 86
87void cursor_warp_to_workspace(struct sway_cursor *cursor, 87void cursor_warp_to_workspace(struct sway_cursor *cursor,
88 struct sway_workspace *workspace); 88 struct sway_workspace *workspace);
89
90uint32_t get_mouse_bindsym(const char *name, char **error);
91
92uint32_t get_mouse_bindcode(const char *name, char **error);
93
94// Considers both bindsym and bindcode
95uint32_t get_mouse_button(const char *name, char **error);
96
89#endif 97#endif
diff --git a/sway/commands/bind.c b/sway/commands/bind.c
index 7994ab2f..be47d412 100644
--- a/sway/commands/bind.c
+++ b/sway/commands/bind.c
@@ -1,10 +1,6 @@
1#define _POSIX_C_SOURCE 200809L 1#define _POSIX_C_SOURCE 200809L
2#include <libevdev/libevdev.h> 2#include <libevdev/libevdev.h>
3#ifdef __linux__
4#include <linux/input-event-codes.h> 3#include <linux/input-event-codes.h>
5#elif __FreeBSD__
6#include <dev/evdev/input-event-codes.h>
7#endif
8#include <xkbcommon/xkbcommon.h> 4#include <xkbcommon/xkbcommon.h>
9#include <xkbcommon/xkbcommon-names.h> 5#include <xkbcommon/xkbcommon-names.h>
10#include <string.h> 6#include <string.h>
@@ -89,69 +85,91 @@ static int key_qsort_cmp(const void *keyp_a, const void *keyp_b) {
89 */ 85 */
90static struct cmd_results *identify_key(const char* name, bool first_key, 86static struct cmd_results *identify_key(const char* name, bool first_key,
91 uint32_t* key_val, enum binding_input_type* type) { 87 uint32_t* key_val, enum binding_input_type* type) {
92 if (*type == BINDING_KEYCODE) { 88 if (*type == BINDING_MOUSECODE) {
93 // check for keycode 89 // check for mouse bindcodes
94 xkb_keycode_t keycode = strtol(name, NULL, 10); 90 char *message = NULL;
95 if (!xkb_keycode_is_legal_ext(keycode)) { 91 uint32_t button = get_mouse_bindcode(name, &message);
96 return cmd_results_new(CMD_INVALID, "bindcode", 92 if (!button) {
97 "Invalid keycode '%s'", name); 93 if (message) {
94 struct cmd_results *error =
95 cmd_results_new(CMD_INVALID, "bindcode", message);
96 free(message);
97 return error;
98 } else {
99 return cmd_results_new(CMD_INVALID, "bindcode",
100 "Unknown button code %s", name);
101 }
98 } 102 }
99 *key_val = keycode; 103 *key_val = button;
100 } else { 104 } else if (*type == BINDING_MOUSESYM) {
101 // check for keysym 105 // check for mouse bindsyms (x11 buttons or event names)
102 xkb_keysym_t keysym = xkb_keysym_from_name(name, 106 char *message = NULL;
103 XKB_KEYSYM_CASE_INSENSITIVE); 107 uint32_t button = get_mouse_bindsym(name, &message);
104 108 if (!button) {
105 // Check for mouse binding 109 if (message) {
106 uint32_t button = 0; 110 struct cmd_results *error =
107 if (strncasecmp(name, "button", strlen("button")) == 0) { 111 cmd_results_new(CMD_INVALID, "bindsym", message);
108 // Map to x11 mouse buttons 112 free(message);
109 button = name[strlen("button")] - '0'; 113 return error;
110 if (button < 1 || button > 9 || strlen(name) > strlen("button0")) { 114 } else if (!button) {
111 return cmd_results_new(CMD_INVALID, "bindsym", 115 return cmd_results_new(CMD_INVALID, "bindsym",
112 "Only buttons 1-9 are supported. For other mouse " 116 "Unknown button %s", name);
113 "buttons, use the name of the event code.");
114 } 117 }
115 uint32_t buttons[] = {BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, 118 }
116 SWAY_SCROLL_UP, SWAY_SCROLL_DOWN, SWAY_SCROLL_LEFT, 119 *key_val = button;
117 SWAY_SCROLL_RIGHT, BTN_SIDE, BTN_EXTRA}; 120 } else if (*type == BINDING_KEYCODE) {
118 button = buttons[button - 1]; 121 // check for keycode. If it is the first key, allow mouse bindcodes
119 } else if (strncmp(name, "BTN_", strlen("BTN_")) == 0) { 122 if (first_key) {
120 // Get event code 123 char *message = NULL;
121 int code = libevdev_event_code_from_name(EV_KEY, name); 124 uint32_t button = get_mouse_bindcode(name, &message);
122 if (code == -1) { 125 free(message);
123 return cmd_results_new(CMD_INVALID, "bindsym", 126 if (button) {
124 "Invalid event code name %s", name); 127 *type = BINDING_MOUSECODE;
128 *key_val = button;
129 return NULL;
125 } 130 }
126 button = code;
127 } 131 }
128 132
129 if (*type == BINDING_KEYSYM) { 133 xkb_keycode_t keycode = strtol(name, NULL, 10);
130 if (button) { 134 if (!xkb_keycode_is_legal_ext(keycode)) {
131 if (first_key) { 135 if (first_key) {
132 *type = BINDING_MOUSE; 136 return cmd_results_new(CMD_INVALID, "bindcode",
133 *key_val = button; 137 "Invalid keycode or button code '%s'", name);
134 } else {
135 return cmd_results_new(CMD_INVALID, "bindsym",
136 "Mixed button '%s' into key sequence", name);
137 }
138 } else if (keysym) {
139 *key_val = keysym;
140 } else { 138 } else {
141 return cmd_results_new(CMD_INVALID, "bindsym", 139 return cmd_results_new(CMD_INVALID, "bindcode",
142 "Unknown key '%s'", name); 140 "Invalid keycode '%s'", name);
143 } 141 }
144 } else { 142 }
145 if (button) { 143 *key_val = keycode;
144 } else {
145 // check for keysym. If it is the first key, allow mouse bindsyms
146 if (first_key) {
147 char *message = NULL;
148 uint32_t button = get_mouse_bindsym(name, &message);
149 if (message) {
150 struct cmd_results *error =
151 cmd_results_new(CMD_INVALID, "bindsym", message);
152 free(message);
153 return error;
154 } else if (button) {
155 *type = BINDING_MOUSESYM;
146 *key_val = button; 156 *key_val = button;
147 } else if (keysym) { 157 return NULL;
158 }
159 }
160
161 xkb_keysym_t keysym = xkb_keysym_from_name(name,
162 XKB_KEYSYM_CASE_INSENSITIVE);
163 if (!keysym) {
164 if (first_key) {
148 return cmd_results_new(CMD_INVALID, "bindsym", 165 return cmd_results_new(CMD_INVALID, "bindsym",
149 "Mixed keysym '%s' into button sequence", name); 166 "Unknown key or button '%s'", name);
150 } else { 167 } else {
151 return cmd_results_new(CMD_INVALID, "bindsym", 168 return cmd_results_new(CMD_INVALID, "bindsym",
152 "Unknown button '%s'", name); 169 "Unknown key '%s'", name);
153 } 170 }
154 } 171 }
172 *key_val = keysym;
155 } 173 }
156 return NULL; 174 return NULL;
157} 175}
@@ -205,7 +223,8 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
205 } 223 }
206 if (binding->flags & (BINDING_BORDER | BINDING_CONTENTS | BINDING_TITLEBAR) 224 if (binding->flags & (BINDING_BORDER | BINDING_CONTENTS | BINDING_TITLEBAR)
207 || exclude_titlebar) { 225 || exclude_titlebar) {
208 binding->type = BINDING_MOUSE; 226 binding->type = binding->type == BINDING_KEYCODE ?
227 BINDING_MOUSECODE : BINDING_MOUSESYM;
209 } 228 }
210 229
211 if (argc < 2) { 230 if (argc < 2) {
@@ -253,7 +272,8 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
253 // that this is one 272 // that this is one
254 if (exclude_titlebar) { 273 if (exclude_titlebar) {
255 binding->flags &= ~BINDING_TITLEBAR; 274 binding->flags &= ~BINDING_TITLEBAR;
256 } else if (binding->type == BINDING_MOUSE) { 275 } else if (binding->type == BINDING_MOUSECODE
276 || binding->type == BINDING_MOUSESYM) {
257 binding->flags |= BINDING_TITLEBAR; 277 binding->flags |= BINDING_TITLEBAR;
258 } 278 }
259 279
diff --git a/sway/commands/move.c b/sway/commands/move.c
index 09f19c3f..72e177e8 100644
--- a/sway/commands/move.c
+++ b/sway/commands/move.c
@@ -154,6 +154,8 @@ static void container_move_to_container_from_direction(
154static void container_move_to_workspace_from_direction( 154static void container_move_to_workspace_from_direction(
155 struct sway_container *container, struct sway_workspace *workspace, 155 struct sway_container *container, struct sway_workspace *workspace,
156 enum wlr_direction move_dir) { 156 enum wlr_direction move_dir) {
157 container->width = container->height = 0;
158
157 if (is_parallel(workspace->layout, move_dir)) { 159 if (is_parallel(workspace->layout, move_dir)) {
158 wlr_log(WLR_DEBUG, "Reparenting container (parallel)"); 160 wlr_log(WLR_DEBUG, "Reparenting container (parallel)");
159 int index = 161 int index =
diff --git a/sway/commands/seat/cursor.c b/sway/commands/seat/cursor.c
index b4728543..1fbc68a1 100644
--- a/sway/commands/seat/cursor.c
+++ b/sway/commands/seat/cursor.c
@@ -1,9 +1,5 @@
1#define _POSIX_C_SOURCE 200809L 1#define _POSIX_C_SOURCE 200809L
2#ifdef __linux__
3#include <linux/input-event-codes.h> 2#include <linux/input-event-codes.h>
4#elif __FreeBSD__
5#include <dev/evdev/input-event-codes.h>
6#endif
7 3
8#include <strings.h> 4#include <strings.h>
9#include <wlr/types/wlr_cursor.h> 5#include <wlr/types/wlr_cursor.h>
diff --git a/sway/config.c b/sway/config.c
index b2742327..ea9f23dd 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -13,11 +13,7 @@
13#include <limits.h> 13#include <limits.h>
14#include <dirent.h> 14#include <dirent.h>
15#include <strings.h> 15#include <strings.h>
16#ifdef __linux__
17#include <linux/input-event-codes.h> 16#include <linux/input-event-codes.h>
18#elif __FreeBSD__
19#include <dev/evdev/input-event-codes.h>
20#endif
21#include <wlr/types/wlr_output.h> 17#include <wlr/types/wlr_output.h>
22#include "sway/input/input-manager.h" 18#include "sway/input/input-manager.h"
23#include "sway/input/seat.h" 19#include "sway/input/seat.h"
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 510030ae..9af7ef57 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -1,13 +1,11 @@
1#define _POSIX_C_SOURCE 200809L 1#define _POSIX_C_SOURCE 200809L
2#include <math.h> 2#include <math.h>
3#include <libevdev/libevdev.h> 3#include <libevdev/libevdev.h>
4#ifdef __linux__
5#include <linux/input-event-codes.h> 4#include <linux/input-event-codes.h>
6#elif __FreeBSD__ 5#include <errno.h>
7#include <dev/evdev/input-event-codes.h>
8#endif
9#include <float.h> 6#include <float.h>
10#include <limits.h> 7#include <limits.h>
8#include <strings.h>
11#include <wlr/types/wlr_cursor.h> 9#include <wlr/types/wlr_cursor.h>
12#include <wlr/types/wlr_xcursor_manager.h> 10#include <wlr/types/wlr_xcursor_manager.h>
13#include <wlr/types/wlr_idle.h> 11#include <wlr/types/wlr_idle.h>
@@ -89,6 +87,10 @@ static struct sway_node *node_at_coords(
89 return NULL; 87 return NULL;
90 } 88 }
91 struct sway_output *output = wlr_output->data; 89 struct sway_output *output = wlr_output->data;
90 if (!output) {
91 // output is being destroyed
92 return NULL;
93 }
92 double ox = lx, oy = ly; 94 double ox = lx, oy = ly;
93 wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy); 95 wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy);
94 96
@@ -1096,6 +1098,8 @@ static void dispatch_cursor_axis(struct sway_cursor *cursor,
1096 enum wlr_edges edge = cont ? find_edge(cont, cursor) : WLR_EDGE_NONE; 1098 enum wlr_edges edge = cont ? find_edge(cont, cursor) : WLR_EDGE_NONE;
1097 bool on_border = edge != WLR_EDGE_NONE; 1099 bool on_border = edge != WLR_EDGE_NONE;
1098 bool on_titlebar = cont && !on_border && !surface; 1100 bool on_titlebar = cont && !on_border && !surface;
1101 bool on_titlebar_border = cont && on_border &&
1102 cursor->cursor->y < cont->content_y;
1099 bool on_contents = cont && !on_border && surface; 1103 bool on_contents = cont && !on_border && surface;
1100 float scroll_factor = 1104 float scroll_factor =
1101 (ic == NULL || ic->scroll_factor == FLT_MIN) ? 1.0f : ic->scroll_factor; 1105 (ic == NULL || ic->scroll_factor == FLT_MIN) ? 1.0f : ic->scroll_factor;
@@ -1121,7 +1125,7 @@ static void dispatch_cursor_axis(struct sway_cursor *cursor,
1121 } 1125 }
1122 1126
1123 // Scrolling on a tabbed or stacked title bar (handled as press event) 1127 // Scrolling on a tabbed or stacked title bar (handled as press event)
1124 if (!handled && on_titlebar) { 1128 if (!handled && (on_titlebar || on_titlebar_border)) {
1125 enum sway_container_layout layout = container_parent_layout(cont); 1129 enum sway_container_layout layout = container_parent_layout(cont);
1126 if (layout == L_TABBED || layout == L_STACKED) { 1130 if (layout == L_TABBED || layout == L_STACKED) {
1127 struct sway_node *tabcontainer = node_get_parent(node); 1131 struct sway_node *tabcontainer = node_get_parent(node);
@@ -1531,3 +1535,66 @@ void cursor_warp_to_workspace(struct sway_cursor *cursor,
1531 1535
1532 wlr_cursor_warp(cursor->cursor, NULL, x, y); 1536 wlr_cursor_warp(cursor->cursor, NULL, x, y);
1533} 1537}
1538
1539uint32_t get_mouse_bindsym(const char *name, char **error) {
1540 if (strncasecmp(name, "button", strlen("button")) == 0) {
1541 // Map to x11 mouse buttons
1542 int number = name[strlen("button")] - '0';
1543 if (number < 1 || number > 9 || strlen(name) > strlen("button0")) {
1544 *error = strdup("Only buttons 1-9 are supported. For other mouse "
1545 "buttons, use the name of the event code.");
1546 return 0;
1547 }
1548 static const uint32_t buttons[] = {BTN_LEFT, BTN_MIDDLE, BTN_RIGHT,
1549 SWAY_SCROLL_UP, SWAY_SCROLL_DOWN, SWAY_SCROLL_LEFT,
1550 SWAY_SCROLL_RIGHT, BTN_SIDE, BTN_EXTRA};
1551 return buttons[number - 1];
1552 } else if (strncmp(name, "BTN_", strlen("BTN_")) == 0) {
1553 // Get event code from name
1554 int code = libevdev_event_code_from_name(EV_KEY, name);
1555 if (code == -1) {
1556 size_t len = snprintf(NULL, 0, "Unknown event %s", name) + 1;
1557 *error = malloc(len);
1558 if (*error) {
1559 snprintf(*error, len, "Unknown event %s", name);
1560 }
1561 return 0;
1562 }
1563 return code;
1564 }
1565 return 0;
1566}
1567
1568uint32_t get_mouse_bindcode(const char *name, char **error) {
1569 // Validate event code
1570 errno = 0;
1571 char *endptr;
1572 int code = strtol(name, &endptr, 10);
1573 if (endptr == name && code <= 0) {
1574 *error = strdup("Button event code must be a positive integer.");
1575 return 0;
1576 } else if (errno == ERANGE) {
1577 *error = strdup("Button event code out of range.");
1578 return 0;
1579 }
1580 const char *event = libevdev_event_code_get_name(EV_KEY, code);
1581 if (!event || strncmp(event, "BTN_", strlen("BTN_")) != 0) {
1582 size_t len = snprintf(NULL, 0, "Event code %d (%s) is not a button",
1583 code, event) + 1;
1584 *error = malloc(len);
1585 if (*error) {
1586 snprintf(*error, len, "Event code %d (%s) is not a button",
1587 code, event);
1588 }
1589 return 0;
1590 }
1591 return code;
1592}
1593
1594uint32_t get_mouse_button(const char *name, char **error) {
1595 uint32_t button = get_mouse_bindsym(name, error);
1596 if (!button && !error) {
1597 button = get_mouse_bindcode(name, error);
1598 }
1599 return button;
1600}
diff --git a/sway/input/seat.c b/sway/input/seat.c
index 41a3a4df..a8df5b99 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -1,11 +1,7 @@
1#define _POSIX_C_SOURCE 200809L 1#define _POSIX_C_SOURCE 200809L
2#include <assert.h> 2#include <assert.h>
3#include <errno.h> 3#include <errno.h>
4#ifdef __linux__
5#include <linux/input-event-codes.h> 4#include <linux/input-event-codes.h>
6#elif __FreeBSD__
7#include <dev/evdev/input-event-codes.h>
8#endif
9#include <strings.h> 5#include <strings.h>
10#include <time.h> 6#include <time.h>
11#include <wlr/types/wlr_cursor.h> 7#include <wlr/types/wlr_cursor.h>
diff --git a/sway/ipc-server.c b/sway/ipc-server.c
index 28546d41..ff1bc89f 100644
--- a/sway/ipc-server.c
+++ b/sway/ipc-server.c
@@ -1,10 +1,6 @@
1// See https://i3wm.org/docs/ipc.html for protocol information 1// See https://i3wm.org/docs/ipc.html for protocol information
2#define _POSIX_C_SOURCE 200112L 2#define _POSIX_C_SOURCE 200112L
3#ifdef __linux__
4#include <linux/input-event-codes.h> 3#include <linux/input-event-codes.h>
5#elif __FreeBSD__
6#include <dev/evdev/input-event-codes.h>
7#endif
8#include <assert.h> 4#include <assert.h>
9#include <errno.h> 5#include <errno.h>
10#include <fcntl.h> 6#include <fcntl.h>
@@ -449,8 +445,12 @@ void ipc_event_binding(struct sway_binding *binding) {
449 json_object_object_add(json_binding, "input_code", json_object_new_int(input_code)); 445 json_object_object_add(json_binding, "input_code", json_object_new_int(input_code));
450 json_object_object_add(json_binding, "symbols", symbols); 446 json_object_object_add(json_binding, "symbols", symbols);
451 json_object_object_add(json_binding, "symbol", symbol); 447 json_object_object_add(json_binding, "symbol", symbol);
452 json_object_object_add(json_binding, "input_type", binding->type == BINDING_MOUSE ? 448
453 json_object_new_string("mouse") : json_object_new_string("keyboard")); 449 bool mouse = binding->type == BINDING_MOUSECODE ||
450 binding->type == BINDING_MOUSESYM;
451 json_object_object_add(json_binding, "input_type", mouse
452 ? json_object_new_string("mouse")
453 : json_object_new_string("keyboard"));
454 454
455 json_object *json = json_object_new_object(); 455 json_object *json = json_object_new_object();
456 json_object_object_add(json, "change", json_object_new_string("run")); 456 json_object_object_add(json, "change", json_object_new_string("run"));
diff --git a/sway/sway.5.scd b/sway/sway.5.scd
index 3757a097..3398ad58 100644
--- a/sway/sway.5.scd
+++ b/sway/sway.5.scd
@@ -302,7 +302,7 @@ runtime.
302``` 302```
303 303
304 *bindcode* [--release|--locked] [--input-device=<device>] [--no-warn] <code> <command> 304 *bindcode* [--release|--locked] [--input-device=<device>] [--no-warn] <code> <command>
305 is also available for binding with key codes instead of key names. 305 is also available for binding with key/button codes instead of key/button names.
306 306
307*client.<class>* <border> <background> <text> <indicator> <child\_border> 307*client.<class>* <border> <background> <text> <indicator> <child\_border>
308 Configures the color of window borders and title bars. All 5 colors are 308 Configures the color of window borders and title bars. All 5 colors are
diff --git a/sway/tree/output.c b/sway/tree/output.c
index 95ab9378..f24be010 100644
--- a/sway/tree/output.c
+++ b/sway/tree/output.c
@@ -58,6 +58,7 @@ struct sway_output *output_create(struct wlr_output *wlr_output) {
58 wlr_output->data = output; 58 wlr_output->data = output;
59 59
60 wl_signal_add(&wlr_output->events.destroy, &output->destroy); 60 wl_signal_add(&wlr_output->events.destroy, &output->destroy);
61 wl_signal_init(&output->events.destroy);
61 62
62 wl_list_insert(&root->all_outputs, &output->link); 63 wl_list_insert(&root->all_outputs, &output->link);
63 64
@@ -76,7 +77,6 @@ void output_enable(struct sway_output *output, struct output_config *oc) {
76 for (size_t i = 0; i < len; ++i) { 77 for (size_t i = 0; i < len; ++i) {
77 wl_list_init(&output->layers[i]); 78 wl_list_init(&output->layers[i]);
78 } 79 }
79 wl_signal_init(&output->events.destroy);
80 80
81 output->enabled = true; 81 output->enabled = true;
82 list_add(root->outputs, output); 82 list_add(root->outputs, output);
diff --git a/swaybar/input.c b/swaybar/input.c
index 7d219be3..620da977 100644
--- a/swaybar/input.c
+++ b/swaybar/input.c
@@ -1,9 +1,5 @@
1#include <assert.h> 1#include <assert.h>
2#ifdef __FreeBSD__
3#include <dev/evdev/input-event-codes.h>
4#else
5#include <linux/input-event-codes.h> 2#include <linux/input-event-codes.h>
6#endif
7#include <stdlib.h> 3#include <stdlib.h>
8#include <wayland-client.h> 4#include <wayland-client.h>
9#include <wayland-cursor.h> 5#include <wayland-cursor.h>
diff --git a/swaybar/render.c b/swaybar/render.c
index 9fe4ee9c..7cbcea07 100644
--- a/swaybar/render.c
+++ b/swaybar/render.c
@@ -90,13 +90,24 @@ static uint32_t render_status_line_text(cairo_t *cairo,
90 return output->height; 90 return output->height;
91} 91}
92 92
93static void render_sharp_line(cairo_t *cairo, uint32_t color, 93static void render_sharp_rectangle(cairo_t *cairo, uint32_t color,
94 double x, double y, double width, double height) { 94 double x, double y, double width, double height) {
95 cairo_save(cairo);
95 cairo_set_source_u32(cairo, color); 96 cairo_set_source_u32(cairo, color);
97 cairo_set_antialias(cairo, CAIRO_ANTIALIAS_NONE);
98 cairo_rectangle(cairo, x, y, width, height);
99 cairo_fill(cairo);
100 cairo_restore(cairo);
101}
102
103static void render_sharp_line(cairo_t *cairo, uint32_t color,
104 double x, double y, double width, double height) {
96 if (width > 1 && height > 1) { 105 if (width > 1 && height > 1) {
97 cairo_rectangle(cairo, x, y, width, height); 106 render_sharp_rectangle(cairo, color, x, y, width, height);
98 cairo_fill(cairo);
99 } else { 107 } else {
108 cairo_save(cairo);
109 cairo_set_source_u32(cairo, color);
110 cairo_set_antialias(cairo, CAIRO_ANTIALIAS_NONE);
100 if (width == 1) { 111 if (width == 1) {
101 x += 0.5; 112 x += 0.5;
102 height += y; 113 height += y;
@@ -111,6 +122,7 @@ static void render_sharp_line(cairo_t *cairo, uint32_t color,
111 cairo_set_line_width(cairo, 1.0); 122 cairo_set_line_width(cairo, 1.0);
112 cairo_line_to(cairo, width, height); 123 cairo_line_to(cairo, width, height);
113 cairo_stroke(cairo); 124 cairo_stroke(cairo);
125 cairo_restore(cairo);
114 } 126 }
115} 127}
116 128
@@ -141,7 +153,7 @@ static uint32_t render_status_block(cairo_t *cairo,
141 output->scale, block->markup, "%s", block->full_text); 153 output->scale, block->markup, "%s", block->full_text);
142 154
143 int margin = 3 * output->scale; 155 int margin = 3 * output->scale;
144 int ws_vertical_padding = WS_VERTICAL_PADDING * 2; 156 double ws_vertical_padding = WS_VERTICAL_PADDING * 2 * output->scale;
145 157
146 int width = text_width; 158 int width = text_width;
147 if (width < block->min_width) { 159 if (width < block->min_width) {
@@ -157,12 +169,12 @@ static uint32_t render_status_block(cairo_t *cairo,
157 169
158 *x -= width; 170 *x -= width;
159 if ((block->border || block->urgent) && block->border_left > 0) { 171 if ((block->border || block->urgent) && block->border_left > 0) {
160 *x -= (block->border_left + margin); 172 *x -= (block->border_left * output->scale + margin);
161 block_width += block->border_left + margin; 173 block_width += block->border_left * output->scale + margin;
162 } 174 }
163 if ((block->border || block->urgent) && block->border_right > 0) { 175 if ((block->border || block->urgent) && block->border_right > 0) {
164 *x -= (block->border_right + margin); 176 *x -= (block->border_right * output->scale + margin);
165 block_width += block->border_right + margin; 177 block_width += block->border_right * output->scale + margin;
166 } 178 }
167 179
168 int sep_width, sep_height; 180 int sep_width, sep_height;
@@ -199,48 +211,41 @@ static uint32_t render_status_block(cairo_t *cairo,
199 wl_list_insert(&output->hotspots, &hotspot->link); 211 wl_list_insert(&output->hotspots, &hotspot->link);
200 } 212 }
201 213
202 double pos = *x; 214 double x_pos = *x;
215 double y_pos = WS_VERTICAL_PADDING * output->scale;
216 double render_height = height - ws_vertical_padding + output->scale;
203 217
204 uint32_t bg_color = block->urgent 218 uint32_t bg_color = block->urgent
205 ? config->colors.urgent_workspace.background : block->background; 219 ? config->colors.urgent_workspace.background : block->background;
206 if (bg_color) { 220 if (bg_color) {
207 cairo_set_source_u32(cairo, bg_color); 221 render_sharp_rectangle(cairo, bg_color, x_pos, y_pos,
208 cairo_rectangle(cairo, pos - 0.5 * output->scale, 222 block_width, render_height);
209 output->scale, width, height);
210 cairo_fill(cairo);
211 } 223 }
212 224
213 uint32_t border_color = block->urgent 225 uint32_t border_color = block->urgent
214 ? config->colors.urgent_workspace.border : block->border; 226 ? config->colors.urgent_workspace.border : block->border;
215 if (border_color && block->border_top > 0) { 227 if (border_color && block->border_top > 0) {
216 render_sharp_line(cairo, border_color, 228 render_sharp_line(cairo, border_color, x_pos, y_pos,
217 pos - 0.5 * output->scale, output->scale, 229 block_width, block->border_top * output->scale);
218 text_width, block->border_top);
219 } 230 }
220 if (border_color && block->border_bottom > 0) { 231 if (border_color && block->border_bottom > 0) {
221 render_sharp_line(cairo, border_color, 232 render_sharp_line(cairo, border_color, x_pos,
222 pos - 0.5 * output->scale, 233 y_pos + render_height - block->border_bottom * output->scale,
223 height - output->scale - block->border_bottom, 234 block_width, block->border_bottom * output->scale);
224 text_width, block->border_bottom);
225 }
226 if (border_color != 0 && block->border_left > 0) {
227 render_sharp_line(cairo, border_color,
228 pos - 0.5 * output->scale, output->scale,
229 block->border_left, height);
230 } 235 }
231 if (border_color != 0 && block->border_right > 0) { 236 if (border_color && block->border_left > 0) {
232 render_sharp_line(cairo, border_color, 237 render_sharp_line(cairo, border_color, x_pos, y_pos,
233 pos - 0.5 * output->scale + text_width, output->scale, 238 block->border_left * output->scale, render_height);
234 block->border_right, height); 239 x_pos += block->border_left * output->scale + margin;
235 } 240 }
236 241
237 double offset = 0; 242 double offset = 0;
238 if (strncmp(block->align, "left", 5) == 0) { 243 if (strncmp(block->align, "left", 5) == 0) {
239 offset = pos; 244 offset = x_pos;
240 } else if (strncmp(block->align, "right", 5) == 0) { 245 } else if (strncmp(block->align, "right", 5) == 0) {
241 offset = pos + width - text_width; 246 offset = x_pos + width - text_width;
242 } else if (strncmp(block->align, "center", 6) == 0) { 247 } else if (strncmp(block->align, "center", 6) == 0) {
243 offset = pos + (width - text_width) / 2; 248 offset = x_pos + (width - text_width) / 2;
244 } 249 }
245 cairo_move_to(cairo, offset, height / 2.0 - text_height / 2.0); 250 cairo_move_to(cairo, offset, height / 2.0 - text_height / 2.0);
246 uint32_t color = block->color ? *block->color : config->colors.statusline; 251 uint32_t color = block->color ? *block->color : config->colors.statusline;
@@ -248,14 +253,13 @@ static uint32_t render_status_block(cairo_t *cairo,
248 cairo_set_source_u32(cairo, color); 253 cairo_set_source_u32(cairo, color);
249 pango_printf(cairo, config->font, output->scale, 254 pango_printf(cairo, config->font, output->scale,
250 block->markup, "%s", block->full_text); 255 block->markup, "%s", block->full_text);
251 pos += width; 256 x_pos += width;
252 257
253 if (block->border && block->border_right > 0) { 258 if (block->border && block->border_right > 0) {
254 pos += margin; 259 x_pos += margin;
255 render_sharp_line(cairo, block->border, 260 render_sharp_line(cairo, border_color, x_pos, y_pos,
256 pos - 0.5 * output->scale, output->scale, 261 block->border_right * output->scale, render_height);
257 block->border_right, height); 262 x_pos += block->border_right * output->scale;
258 pos += block->border_right;
259 } 263 }
260 264
261 if (!edge && block->separator) { 265 if (!edge && block->separator) {
@@ -265,14 +269,14 @@ static uint32_t render_status_block(cairo_t *cairo,
265 cairo_set_source_u32(cairo, config->colors.separator); 269 cairo_set_source_u32(cairo, config->colors.separator);
266 } 270 }
267 if (config->sep_symbol) { 271 if (config->sep_symbol) {
268 offset = pos + (sep_block_width - sep_width) / 2; 272 offset = x_pos + (sep_block_width - sep_width) / 2;
269 cairo_move_to(cairo, offset, height / 2.0 - sep_height / 2.0); 273 cairo_move_to(cairo, offset, height / 2.0 - sep_height / 2.0);
270 pango_printf(cairo, config->font, output->scale, false, 274 pango_printf(cairo, config->font, output->scale, false,
271 "%s", config->sep_symbol); 275 "%s", config->sep_symbol);
272 } else { 276 } else {
273 cairo_set_line_width(cairo, 1); 277 cairo_set_line_width(cairo, 1);
274 cairo_move_to(cairo, pos + sep_block_width / 2, margin); 278 cairo_move_to(cairo, x_pos + sep_block_width / 2, margin);
275 cairo_line_to(cairo, pos + sep_block_width / 2, height - margin); 279 cairo_line_to(cairo, x_pos + sep_block_width / 2, height - margin);
276 cairo_stroke(cairo); 280 cairo_stroke(cairo);
277 } 281 }
278 } 282 }