diff options
-rw-r--r-- | common/cairo.c | 16 | ||||
-rw-r--r-- | common/pango.c | 58 | ||||
-rw-r--r-- | contrib/awesome.config | 63 | ||||
-rw-r--r-- | include/cairo.h | 2 | ||||
-rw-r--r-- | include/pango.h | 14 | ||||
-rw-r--r-- | include/sway/commands.h | 9 | ||||
-rw-r--r-- | include/swaybar/bar.h | 1 | ||||
-rw-r--r-- | include/swaylock/swaylock.h | 1 | ||||
-rw-r--r-- | sway/commands.c | 16 | ||||
-rw-r--r-- | sway/commands/bind.c | 2 | ||||
-rw-r--r-- | sway/desktop/transaction.c | 11 | ||||
-rw-r--r-- | sway/desktop/xdg_shell.c | 2 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 2 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 2 | ||||
-rw-r--r-- | sway/ipc-server.c | 2 | ||||
-rw-r--r-- | sway/main.c | 2 | ||||
-rw-r--r-- | sway/tree/container.c | 8 | ||||
-rw-r--r-- | sway/tree/root.c | 6 | ||||
-rw-r--r-- | sway/tree/view.c | 19 | ||||
-rw-r--r-- | sway/tree/workspace.c | 10 | ||||
-rw-r--r-- | swaybar/bar.c | 8 | ||||
-rw-r--r-- | swaybar/render.c | 7 | ||||
-rw-r--r-- | swaybar/status_line.c | 10 | ||||
-rw-r--r-- | swaylock/main.c | 8 | ||||
-rw-r--r-- | swaylock/render.c | 7 |
25 files changed, 130 insertions, 156 deletions
diff --git a/common/cairo.c b/common/cairo.c index c267c77c..e8231484 100644 --- a/common/cairo.c +++ b/common/cairo.c | |||
@@ -13,6 +13,22 @@ void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { | |||
13 | (color >> (0*8) & 0xFF) / 255.0); | 13 | (color >> (0*8) & 0xFF) / 255.0); |
14 | } | 14 | } |
15 | 15 | ||
16 | cairo_subpixel_order_t to_cairo_subpixel_order(enum wl_output_subpixel subpixel) { | ||
17 | switch (subpixel) { | ||
18 | case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB: | ||
19 | return CAIRO_SUBPIXEL_ORDER_RGB; | ||
20 | case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR: | ||
21 | return CAIRO_SUBPIXEL_ORDER_BGR; | ||
22 | case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB: | ||
23 | return CAIRO_SUBPIXEL_ORDER_VRGB; | ||
24 | case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR: | ||
25 | return CAIRO_SUBPIXEL_ORDER_VBGR; | ||
26 | default: | ||
27 | return CAIRO_SUBPIXEL_ORDER_DEFAULT; | ||
28 | } | ||
29 | return CAIRO_SUBPIXEL_ORDER_DEFAULT; | ||
30 | } | ||
31 | |||
16 | cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image, | 32 | cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image, |
17 | int width, int height) { | 33 | int width, int height) { |
18 | int image_width = cairo_image_surface_get_width(image); | 34 | int image_width = cairo_image_surface_get_width(image); |
diff --git a/common/pango.c b/common/pango.c index ea71ac4a..ba74692e 100644 --- a/common/pango.c +++ b/common/pango.c | |||
@@ -6,67 +6,47 @@ | |||
6 | #include <stdio.h> | 6 | #include <stdio.h> |
7 | #include <stdlib.h> | 7 | #include <stdlib.h> |
8 | #include <string.h> | 8 | #include <string.h> |
9 | #include "cairo.h" | ||
9 | #include "log.h" | 10 | #include "log.h" |
11 | #include "stringop.h" | ||
10 | 12 | ||
11 | int escape_markup_text(const char *src, char *dest, int dest_length) { | 13 | size_t escape_markup_text(const char *src, char *dest) { |
12 | int length = 0; | 14 | size_t length = 0; |
15 | if (dest) { | ||
16 | dest[0] = '\0'; | ||
17 | } | ||
13 | 18 | ||
14 | while (src[0]) { | 19 | while (src[0]) { |
15 | switch (src[0]) { | 20 | switch (src[0]) { |
16 | case '&': | 21 | case '&': |
17 | length += 5; | 22 | length += 5; |
18 | if (dest && dest_length - length >= 0) { | 23 | lenient_strcat(dest, "&"); |
19 | dest += sprintf(dest, "%s", "&"); | ||
20 | } else { | ||
21 | dest_length = -1; | ||
22 | } | ||
23 | break; | 24 | break; |
24 | case '<': | 25 | case '<': |
25 | length += 4; | 26 | length += 4; |
26 | if (dest && dest_length - length >= 0) { | 27 | lenient_strcat(dest, "<"); |
27 | dest += sprintf(dest, "%s", "<"); | ||
28 | } else { | ||
29 | dest_length = -1; | ||
30 | } | ||
31 | break; | 28 | break; |
32 | case '>': | 29 | case '>': |
33 | length += 4; | 30 | length += 4; |
34 | if (dest && dest_length - length >= 0) { | 31 | lenient_strcat(dest, ">"); |
35 | dest += sprintf(dest, "%s", ">"); | ||
36 | } else { | ||
37 | dest_length = -1; | ||
38 | } | ||
39 | break; | 32 | break; |
40 | case '\'': | 33 | case '\'': |
41 | length += 6; | 34 | length += 6; |
42 | if (dest && dest_length - length >= 0) { | 35 | lenient_strcat(dest, "'"); |
43 | dest += sprintf(dest, "%s", "'"); | ||
44 | } else { | ||
45 | dest_length = -1; | ||
46 | } | ||
47 | break; | 36 | break; |
48 | case '"': | 37 | case '"': |
49 | length += 6; | 38 | length += 6; |
50 | if (dest && dest_length - length >= 0) { | 39 | lenient_strcat(dest, """); |
51 | dest += sprintf(dest, "%s", """); | ||
52 | } else { | ||
53 | dest_length = -1; | ||
54 | } | ||
55 | break; | 40 | break; |
56 | default: | 41 | default: |
57 | length += 1; | 42 | if (dest) { |
58 | if (dest && dest_length - length >= 0) { | 43 | dest[length] = *src; |
59 | *(dest++) = *src; | 44 | dest[length + 1] = '\0'; |
60 | } else { | ||
61 | dest_length = -1; | ||
62 | } | 45 | } |
46 | length += 1; | ||
63 | } | 47 | } |
64 | src++; | 48 | src++; |
65 | } | 49 | } |
66 | // if we could not fit the escaped string in dest, return -1 | ||
67 | if (dest && dest_length == -1) { | ||
68 | return -1; | ||
69 | } | ||
70 | return length; | 50 | return length; |
71 | } | 51 | } |
72 | 52 | ||
@@ -78,7 +58,7 @@ PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, | |||
78 | char *buf; | 58 | char *buf; |
79 | GError *error = NULL; | 59 | GError *error = NULL; |
80 | if (pango_parse_markup(text, -1, 0, &attrs, &buf, NULL, &error)) { | 60 | if (pango_parse_markup(text, -1, 0, &attrs, &buf, NULL, &error)) { |
81 | pango_layout_set_markup(layout, buf, -1); | 61 | pango_layout_set_text(layout, buf, -1); |
82 | free(buf); | 62 | free(buf); |
83 | } else { | 63 | } else { |
84 | wlr_log(WLR_ERROR, "pango_parse_markup '%s' -> error %s", text, | 64 | wlr_log(WLR_ERROR, "pango_parse_markup '%s' -> error %s", text, |
@@ -134,6 +114,10 @@ void pango_printf(cairo_t *cairo, const char *font, | |||
134 | va_end(args); | 114 | va_end(args); |
135 | 115 | ||
136 | PangoLayout *layout = get_pango_layout(cairo, font, buf, scale, markup); | 116 | PangoLayout *layout = get_pango_layout(cairo, font, buf, scale, markup); |
117 | cairo_font_options_t *fo = cairo_font_options_create(); | ||
118 | cairo_get_font_options(cairo, fo); | ||
119 | pango_cairo_context_set_font_options(pango_layout_get_context(layout), fo); | ||
120 | cairo_font_options_destroy(fo); | ||
137 | pango_cairo_update_layout(cairo, layout); | 121 | pango_cairo_update_layout(cairo, layout); |
138 | pango_cairo_show_layout(cairo, layout); | 122 | pango_cairo_show_layout(cairo, layout); |
139 | g_object_unref(layout); | 123 | g_object_unref(layout); |
diff --git a/contrib/awesome.config b/contrib/awesome.config deleted file mode 100644 index 41e17c91..00000000 --- a/contrib/awesome.config +++ /dev/null | |||
@@ -1,63 +0,0 @@ | |||
1 | # | ||
2 | # Replicate some of Awesome's default layout manipulation configuration for Sway | ||
3 | # | ||
4 | # Differences: | ||
5 | # - Layout switching doesn't use the spacebar (i.e. i3/Sway behavior to switch to/from floating windows) | ||
6 | # and uses the 'A' key instead (as in auto) | ||
7 | # - Resizing windows uses i3/Sway's more versatile Mod4+r | ||
8 | # - no tags | ||
9 | # - no Maximize/Minize, alternatives to Maximize would be to switch to Stacked/Tabbed layouts | ||
10 | # via Mod4+w or Mod4+s. | ||
11 | # - kill focused client is available on Mod4+Shift+q (instead of Mod4+Shift+c, which maps to Sway's | ||
12 | # config reload) | ||
13 | # - probably many more ... | ||
14 | |||
15 | # Awesome-style container traversal using Vim-like binding | ||
16 | set $next j | ||
17 | set $prev k | ||
18 | |||
19 | # | ||
20 | # Moving around: | ||
21 | # | ||
22 | # Move your focus around | ||
23 | bindsym $mod+$next focus next | ||
24 | bindsym $mod+$prev focus prev | ||
25 | |||
26 | # _move_ the focused window with the same, but add Shift | ||
27 | bindsym $mod+Shift+$next move next | ||
28 | bindsym $mod+Shift+$prev move prev | ||
29 | |||
30 | # | ||
31 | # Layout: | ||
32 | # | ||
33 | workspace_layout auto left | ||
34 | |||
35 | # This is usually bound to $mod+space, but this works well in practice by keeping | ||
36 | # all the layout switching keys grouped together. | ||
37 | bindsym $mod+a layout auto next | ||
38 | bindsym $mod+Shift+a layout auto prev | ||
39 | |||
40 | # Promote a child to master position in an auto layout | ||
41 | bindsym $mod+Control+Return move first | ||
42 | |||
43 | # Increase/decrease number of master elements in auto layout | ||
44 | bindsym $mod+Shift+h layout auto master inc 1 | ||
45 | bindsym $mod+Shift+l layout auto master inc -1 | ||
46 | |||
47 | # Increase/decrease number of slave element groups in auto layout | ||
48 | bindsym $mod+Control+h layout auto ncol inc 1 | ||
49 | bindsym $mod+Control+l layout auto ncol inc -1 | ||
50 | |||
51 | # | ||
52 | # Resizing containers: | ||
53 | # Again, not really the way Awesome works well, but in spirit with i3/Sway and it works well. | ||
54 | # | ||
55 | mode "resize" { | ||
56 | bindsym Left resize shrink width 20 px | ||
57 | bindsym Down resize grow height 20 px | ||
58 | bindsym Up resize shrink height 20 px | ||
59 | bindsym Right resize grow width 20 px | ||
60 | } | ||
61 | bindsym $mod+r mode "resize" | ||
62 | |||
63 | new_window pixel 1 | ||
diff --git a/include/cairo.h b/include/cairo.h index 31672705..86530b60 100644 --- a/include/cairo.h +++ b/include/cairo.h | |||
@@ -2,8 +2,10 @@ | |||
2 | #define _SWAY_CAIRO_H | 2 | #define _SWAY_CAIRO_H |
3 | #include <stdint.h> | 3 | #include <stdint.h> |
4 | #include <cairo/cairo.h> | 4 | #include <cairo/cairo.h> |
5 | #include <wlr/types/wlr_output.h> | ||
5 | 6 | ||
6 | void cairo_set_source_u32(cairo_t *cairo, uint32_t color); | 7 | void cairo_set_source_u32(cairo_t *cairo, uint32_t color); |
8 | cairo_subpixel_order_t to_cairo_subpixel_order(enum wl_output_subpixel subpixel); | ||
7 | 9 | ||
8 | cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image, | 10 | cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image, |
9 | int width, int height); | 11 | int width, int height); |
diff --git a/include/pango.h b/include/pango.h index 09a535a5..6ab83c16 100644 --- a/include/pango.h +++ b/include/pango.h | |||
@@ -6,17 +6,13 @@ | |||
6 | #include <cairo/cairo.h> | 6 | #include <cairo/cairo.h> |
7 | #include <pango/pangocairo.h> | 7 | #include <pango/pangocairo.h> |
8 | 8 | ||
9 | /* Utility function which escape characters a & < > ' ". | 9 | /** |
10 | * Utility function which escape characters a & < > ' ". | ||
10 | * | 11 | * |
11 | * If the dest parameter is NULL, then the function returns the length of | 12 | * The function returns the length of the escaped string, optionally writing the |
12 | * of the escaped src string. The dest_length doesn't matter. | 13 | * escaped string to dest if provided. |
13 | * | ||
14 | * If the dest parameter is not NULL then the fuction escapes the src string | ||
15 | * an puts the escaped string in dest and returns the lenght of the escaped string. | ||
16 | * The dest_length parameter is the size of dest array. If the size of dest is not | ||
17 | * enough, then the function returns -1. | ||
18 | */ | 14 | */ |
19 | int escape_markup_text(const char *src, char *dest, int dest_length); | 15 | size_t escape_markup_text(const char *src, char *dest); |
20 | PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, | 16 | PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, |
21 | const char *text, double scale, bool markup); | 17 | const char *text, double scale, bool markup); |
22 | void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, | 18 | void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, |
diff --git a/include/sway/commands.h b/include/sway/commands.h index 226cf932..1654eb48 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h | |||
@@ -4,6 +4,8 @@ | |||
4 | #include <wlr/util/edges.h> | 4 | #include <wlr/util/edges.h> |
5 | #include "config.h" | 5 | #include "config.h" |
6 | 6 | ||
7 | struct sway_container; | ||
8 | |||
7 | typedef struct cmd_results *sway_cmd(int argc, char **argv); | 9 | typedef struct cmd_results *sway_cmd(int argc, char **argv); |
8 | 10 | ||
9 | struct cmd_handler { | 11 | struct cmd_handler { |
@@ -50,8 +52,13 @@ struct cmd_handler *find_handler(char *line, struct cmd_handler *cmd_handlers, | |||
50 | int handlers_size); | 52 | int handlers_size); |
51 | /** | 53 | /** |
52 | * Parse and executes a command. | 54 | * Parse and executes a command. |
55 | * | ||
56 | * If the command string contains criteria then the command will be executed on | ||
57 | * all matching containers. Otherwise, it'll run on the `con` container. If | ||
58 | * `con` is NULL then it'll run on the currently focused container. | ||
53 | */ | 59 | */ |
54 | struct cmd_results *execute_command(char *command, struct sway_seat *seat); | 60 | struct cmd_results *execute_command(char *command, struct sway_seat *seat, |
61 | struct sway_container *con); | ||
55 | /** | 62 | /** |
56 | * Parse and handles a command during config file loading. | 63 | * Parse and handles a command during config file loading. |
57 | * | 64 | * |
diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 4065fb8b..29e96159 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h | |||
@@ -81,6 +81,7 @@ struct swaybar_output { | |||
81 | 81 | ||
82 | uint32_t width, height; | 82 | uint32_t width, height; |
83 | int32_t scale; | 83 | int32_t scale; |
84 | enum wl_output_subpixel subpixel; | ||
84 | struct pool_buffer buffers[2]; | 85 | struct pool_buffer buffers[2]; |
85 | struct pool_buffer *current_buffer; | 86 | struct pool_buffer *current_buffer; |
86 | }; | 87 | }; |
diff --git a/include/swaylock/swaylock.h b/include/swaylock/swaylock.h index 950cfaaf..2f0cd34d 100644 --- a/include/swaylock/swaylock.h +++ b/include/swaylock/swaylock.h | |||
@@ -82,6 +82,7 @@ struct swaylock_surface { | |||
82 | bool frame_pending, dirty; | 82 | bool frame_pending, dirty; |
83 | uint32_t width, height; | 83 | uint32_t width, height; |
84 | int32_t scale; | 84 | int32_t scale; |
85 | enum wl_output_subpixel subpixel; | ||
85 | char *output_name; | 86 | char *output_name; |
86 | struct wl_list link; | 87 | struct wl_list link; |
87 | }; | 88 | }; |
diff --git a/sway/commands.c b/sway/commands.c index 07169f1e..5b61f73a 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -237,7 +237,8 @@ static void set_config_node(struct sway_node *node) { | |||
237 | } | 237 | } |
238 | } | 238 | } |
239 | 239 | ||
240 | struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) { | 240 | struct cmd_results *execute_command(char *_exec, struct sway_seat *seat, |
241 | struct sway_container *con) { | ||
241 | // Even though this function will process multiple commands we will only | 242 | // Even though this function will process multiple commands we will only |
242 | // return the last error, if any (for now). (Since we have access to an | 243 | // return the last error, if any (for now). (Since we have access to an |
243 | // error string we could e.g. concatenate all errors there.) | 244 | // error string we could e.g. concatenate all errors there.) |
@@ -256,6 +257,15 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) { | |||
256 | } | 257 | } |
257 | } | 258 | } |
258 | 259 | ||
260 | // This is the container or workspace which this command will run on. | ||
261 | // Ignored if the command string contains criteria. | ||
262 | struct sway_node *node; | ||
263 | if (con) { | ||
264 | node = &con->node; | ||
265 | } else { | ||
266 | node = seat_get_focus_inactive(seat, &root->node); | ||
267 | } | ||
268 | |||
259 | config->handler_context.seat = seat; | 269 | config->handler_context.seat = seat; |
260 | 270 | ||
261 | head = exec; | 271 | head = exec; |
@@ -318,9 +328,7 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) { | |||
318 | } | 328 | } |
319 | 329 | ||
320 | if (!config->handler_context.using_criteria) { | 330 | if (!config->handler_context.using_criteria) { |
321 | // without criteria, the command acts upon the focused | 331 | set_config_node(node); |
322 | // container | ||
323 | set_config_node(seat_get_focus_inactive(seat, &root->node)); | ||
324 | struct cmd_results *res = handler->handle(argc-1, argv+1); | 332 | struct cmd_results *res = handler->handle(argc-1, argv+1); |
325 | if (res->status != CMD_SUCCESS) { | 333 | if (res->status != CMD_SUCCESS) { |
326 | free_argv(argc, argv); | 334 | free_argv(argc, argv); |
diff --git a/sway/commands/bind.c b/sway/commands/bind.c index 047018e0..820c2a6a 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c | |||
@@ -321,7 +321,7 @@ void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding) | |||
321 | } | 321 | } |
322 | 322 | ||
323 | config->handler_context.seat = seat; | 323 | config->handler_context.seat = seat; |
324 | struct cmd_results *results = execute_command(binding->command, NULL); | 324 | struct cmd_results *results = execute_command(binding->command, NULL, NULL); |
325 | if (results->status == CMD_SUCCESS) { | 325 | if (results->status == CMD_SUCCESS) { |
326 | ipc_event_binding(binding_copy); | 326 | ipc_event_binding(binding_copy); |
327 | } else { | 327 | } else { |
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index d747e279..797f6b4c 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <string.h> | 6 | #include <string.h> |
7 | #include <time.h> | 7 | #include <time.h> |
8 | #include <wlr/types/wlr_buffer.h> | 8 | #include <wlr/types/wlr_buffer.h> |
9 | #include "sway/config.h" | ||
9 | #include "sway/debug.h" | 10 | #include "sway/debug.h" |
10 | #include "sway/desktop.h" | 11 | #include "sway/desktop.h" |
11 | #include "sway/desktop/idle_inhibit_v1.h" | 12 | #include "sway/desktop/idle_inhibit_v1.h" |
@@ -390,6 +391,16 @@ static bool should_configure(struct sway_node *node, | |||
390 | } | 391 | } |
391 | struct sway_container_state *cstate = &node->sway_container->current; | 392 | struct sway_container_state *cstate = &node->sway_container->current; |
392 | struct sway_container_state *istate = instruction->container_state; | 393 | struct sway_container_state *istate = instruction->container_state; |
394 | #ifdef HAVE_XWAYLAND | ||
395 | // Xwayland views are position-aware and need to be reconfigured | ||
396 | // when their position changes. | ||
397 | if (node->sway_container->view->type == SWAY_VIEW_XWAYLAND) { | ||
398 | if (cstate->view_x != istate->view_x || | ||
399 | cstate->view_y != istate->view_y) { | ||
400 | return true; | ||
401 | } | ||
402 | } | ||
403 | #endif | ||
393 | if (cstate->view_width == istate->view_width && | 404 | if (cstate->view_width == istate->view_width && |
394 | cstate->view_height == istate->view_height) { | 405 | cstate->view_height == istate->view_height) { |
395 | return false; | 406 | return false; |
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 00448be7..6d1ccdd7 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c | |||
@@ -401,7 +401,7 @@ static void handle_map(struct wl_listener *listener, void *data) { | |||
401 | } else { | 401 | } else { |
402 | if (view->container->parent) { | 402 | if (view->container->parent) { |
403 | arrange_container(view->container->parent); | 403 | arrange_container(view->container->parent); |
404 | } else { | 404 | } else if (view->container->workspace) { |
405 | arrange_workspace(view->container->workspace); | 405 | arrange_workspace(view->container->workspace); |
406 | } | 406 | } |
407 | } | 407 | } |
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index d2c9a68b..95ca396c 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c | |||
@@ -398,7 +398,7 @@ static void handle_map(struct wl_listener *listener, void *data) { | |||
398 | } else { | 398 | } else { |
399 | if (view->container->parent) { | 399 | if (view->container->parent) { |
400 | arrange_container(view->container->parent); | 400 | arrange_container(view->container->parent); |
401 | } else { | 401 | } else if (view->container->workspace) { |
402 | arrange_workspace(view->container->workspace); | 402 | arrange_workspace(view->container->workspace); |
403 | } | 403 | } |
404 | } | 404 | } |
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 3619f202..a12ac854 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -394,7 +394,7 @@ static void handle_map(struct wl_listener *listener, void *data) { | |||
394 | } else { | 394 | } else { |
395 | if (view->container->parent) { | 395 | if (view->container->parent) { |
396 | arrange_container(view->container->parent); | 396 | arrange_container(view->container->parent); |
397 | } else { | 397 | } else if (view->container->workspace) { |
398 | arrange_workspace(view->container->workspace); | 398 | arrange_workspace(view->container->workspace); |
399 | } | 399 | } |
400 | } | 400 | } |
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 8ae265f6..99959c97 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c | |||
@@ -580,7 +580,7 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
580 | switch (client->current_command) { | 580 | switch (client->current_command) { |
581 | case IPC_COMMAND: | 581 | case IPC_COMMAND: |
582 | { | 582 | { |
583 | struct cmd_results *results = execute_command(buf, NULL); | 583 | struct cmd_results *results = execute_command(buf, NULL, NULL); |
584 | transaction_commit_dirty(); | 584 | transaction_commit_dirty(); |
585 | char *json = cmd_results_to_json(results); | 585 | char *json = cmd_results_to_json(results); |
586 | int length = strlen(json); | 586 | int length = strlen(json); |
diff --git a/sway/main.c b/sway/main.c index 3d7cd158..990f5f3a 100644 --- a/sway/main.c +++ b/sway/main.c | |||
@@ -429,7 +429,7 @@ int main(int argc, char **argv) { | |||
429 | wlr_log(WLR_DEBUG, "Running deferred commands"); | 429 | wlr_log(WLR_DEBUG, "Running deferred commands"); |
430 | while (config->cmd_queue->length) { | 430 | while (config->cmd_queue->length) { |
431 | char *line = config->cmd_queue->items[0]; | 431 | char *line = config->cmd_queue->items[0]; |
432 | struct cmd_results *res = execute_command(line, NULL); | 432 | struct cmd_results *res = execute_command(line, NULL, NULL); |
433 | if (res->status != CMD_SUCCESS) { | 433 | if (res->status != CMD_SUCCESS) { |
434 | wlr_log(WLR_ERROR, "Error on line '%s': %s", line, res->error); | 434 | wlr_log(WLR_ERROR, "Error on line '%s': %s", line, res->error); |
435 | } | 435 | } |
diff --git a/sway/tree/container.c b/sway/tree/container.c index b8af7564..53b127b7 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -463,11 +463,17 @@ static void update_title_texture(struct sway_container *con, | |||
463 | cairo_surface_t *surface = cairo_image_surface_create( | 463 | cairo_surface_t *surface = cairo_image_surface_create( |
464 | CAIRO_FORMAT_ARGB32, width, height); | 464 | CAIRO_FORMAT_ARGB32, width, height); |
465 | cairo_t *cairo = cairo_create(surface); | 465 | cairo_t *cairo = cairo_create(surface); |
466 | cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); | ||
467 | cairo_font_options_t *fo = cairo_font_options_create(); | ||
468 | cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL); | ||
469 | cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_SUBPIXEL); | ||
470 | cairo_font_options_set_subpixel_order(fo, to_cairo_subpixel_order(output->wlr_output->subpixel)); | ||
471 | cairo_set_font_options(cairo, fo); | ||
472 | cairo_font_options_destroy(fo); | ||
466 | cairo_set_source_rgba(cairo, class->background[0], class->background[1], | 473 | cairo_set_source_rgba(cairo, class->background[0], class->background[1], |
467 | class->background[2], class->background[3]); | 474 | class->background[2], class->background[3]); |
468 | cairo_paint(cairo); | 475 | cairo_paint(cairo); |
469 | PangoContext *pango = pango_cairo_create_context(cairo); | 476 | PangoContext *pango = pango_cairo_create_context(cairo); |
470 | cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); | ||
471 | cairo_set_source_rgba(cairo, class->text[0], class->text[1], | 477 | cairo_set_source_rgba(cairo, class->text[0], class->text[1], |
472 | class->text[2], class->text[3]); | 478 | class->text[2], class->text[3]); |
473 | cairo_move_to(cairo, 0, 0); | 479 | cairo_move_to(cairo, 0, 0); |
diff --git a/sway/tree/root.c b/sway/tree/root.c index ecc04ddb..d6f67bd7 100644 --- a/sway/tree/root.c +++ b/sway/tree/root.c | |||
@@ -265,10 +265,10 @@ void root_for_each_container(void (*f)(struct sway_container *con, void *data), | |||
265 | // Scratchpad | 265 | // Scratchpad |
266 | for (int i = 0; i < root->scratchpad->length; ++i) { | 266 | for (int i = 0; i < root->scratchpad->length; ++i) { |
267 | struct sway_container *container = root->scratchpad->items[i]; | 267 | struct sway_container *container = root->scratchpad->items[i]; |
268 | // If the container has a parent then it's visible on a workspace | 268 | // If the container has a workspace then it's visible on a workspace |
269 | // and will have been iterated in the previous for loop. So we only | 269 | // and will have been iterated in the previous for loop. So we only |
270 | // iterate the hidden scratchpad containers here. | 270 | // iterate the hidden scratchpad containers here. |
271 | if (!container->parent) { | 271 | if (!container->workspace) { |
272 | f(container, data); | 272 | f(container, data); |
273 | container_for_each_child(container, f, data); | 273 | container_for_each_child(container, f, data); |
274 | } | 274 | } |
@@ -311,7 +311,7 @@ struct sway_container *root_find_container( | |||
311 | // Scratchpad | 311 | // Scratchpad |
312 | for (int i = 0; i < root->scratchpad->length; ++i) { | 312 | for (int i = 0; i < root->scratchpad->length; ++i) { |
313 | struct sway_container *container = root->scratchpad->items[i]; | 313 | struct sway_container *container = root->scratchpad->items[i]; |
314 | if (!container->parent) { | 314 | if (!container->workspace) { |
315 | if (test(container, data)) { | 315 | if (test(container, data)) { |
316 | return container; | 316 | return container; |
317 | } | 317 | } |
diff --git a/sway/tree/view.c b/sway/tree/view.c index 4398f518..e370443c 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -391,8 +391,6 @@ static bool view_has_executed_criteria(struct sway_view *view, | |||
391 | } | 391 | } |
392 | 392 | ||
393 | void view_execute_criteria(struct sway_view *view) { | 393 | void view_execute_criteria(struct sway_view *view) { |
394 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
395 | struct sway_node *prior_focus = seat_get_focus(seat); | ||
396 | list_t *criterias = criteria_for_view(view, CT_COMMAND); | 394 | list_t *criterias = criteria_for_view(view, CT_COMMAND); |
397 | for (int i = 0; i < criterias->length; i++) { | 395 | for (int i = 0; i < criterias->length; i++) { |
398 | struct criteria *criteria = criterias->items[i]; | 396 | struct criteria *criteria = criterias->items[i]; |
@@ -403,16 +401,12 @@ void view_execute_criteria(struct sway_view *view) { | |||
403 | } | 401 | } |
404 | wlr_log(WLR_DEBUG, "for_window '%s' matches view %p, cmd: '%s'", | 402 | wlr_log(WLR_DEBUG, "for_window '%s' matches view %p, cmd: '%s'", |
405 | criteria->raw, view, criteria->cmdlist); | 403 | criteria->raw, view, criteria->cmdlist); |
406 | seat_set_focus_container(seat, view->container); | ||
407 | list_add(view->executed_criteria, criteria); | 404 | list_add(view->executed_criteria, criteria); |
408 | struct cmd_results *res = execute_command(criteria->cmdlist, NULL); | 405 | struct cmd_results *res = execute_command( |
409 | if (res->status != CMD_SUCCESS) { | 406 | criteria->cmdlist, NULL, view->container); |
410 | wlr_log(WLR_ERROR, "Command '%s' failed: %s", res->input, res->error); | ||
411 | } | ||
412 | free_cmd_results(res); | 407 | free_cmd_results(res); |
413 | } | 408 | } |
414 | list_free(criterias); | 409 | list_free(criterias); |
415 | seat_set_focus(seat, prior_focus); | ||
416 | } | 410 | } |
417 | 411 | ||
418 | static struct sway_workspace *select_workspace(struct sway_view *view) { | 412 | static struct sway_workspace *select_workspace(struct sway_view *view) { |
@@ -785,14 +779,9 @@ static size_t parse_title_format(struct sway_view *view, char *buffer) { | |||
785 | } | 779 | } |
786 | 780 | ||
787 | static char *escape_title(char *buffer) { | 781 | static char *escape_title(char *buffer) { |
788 | int length = escape_markup_text(buffer, NULL, 0); | 782 | size_t length = escape_markup_text(buffer, NULL); |
789 | char *escaped_title = calloc(length + 1, sizeof(char)); | 783 | char *escaped_title = calloc(length + 1, sizeof(char)); |
790 | int result = escape_markup_text(buffer, escaped_title, length); | 784 | escape_markup_text(buffer, escaped_title); |
791 | if (result != length) { | ||
792 | wlr_log(WLR_ERROR, "Could not escape title: %s", buffer); | ||
793 | free(escaped_title); | ||
794 | return buffer; | ||
795 | } | ||
796 | free(buffer); | 785 | free(buffer); |
797 | return escaped_title; | 786 | return escaped_title; |
798 | } | 787 | } |
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 18746430..b0c440c1 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c | |||
@@ -389,13 +389,11 @@ bool workspace_switch(struct sway_workspace *workspace, | |||
389 | struct sway_output *next_output = workspace->output; | 389 | struct sway_output *next_output = workspace->output; |
390 | struct sway_workspace *next_output_prev_ws = | 390 | struct sway_workspace *next_output_prev_ws = |
391 | output_get_active_workspace(next_output); | 391 | output_get_active_workspace(next_output); |
392 | bool has_sticky = false; | ||
393 | if (workspace != next_output_prev_ws) { | 392 | if (workspace != next_output_prev_ws) { |
394 | for (int i = 0; i < next_output_prev_ws->floating->length; ++i) { | 393 | for (int i = 0; i < next_output_prev_ws->floating->length; ++i) { |
395 | struct sway_container *floater = | 394 | struct sway_container *floater = |
396 | next_output_prev_ws->floating->items[i]; | 395 | next_output_prev_ws->floating->items[i]; |
397 | if (floater->is_sticky) { | 396 | if (floater->is_sticky) { |
398 | has_sticky = true; | ||
399 | container_detach(floater); | 397 | container_detach(floater); |
400 | workspace_add_floating(workspace, floater); | 398 | workspace_add_floating(workspace, floater); |
401 | if (&floater->node == focus) { | 399 | if (&floater->node == focus) { |
@@ -414,14 +412,6 @@ bool workspace_switch(struct sway_workspace *workspace, | |||
414 | if (next == NULL) { | 412 | if (next == NULL) { |
415 | next = &workspace->node; | 413 | next = &workspace->node; |
416 | } | 414 | } |
417 | if (has_sticky) { | ||
418 | // If there's a sticky container, we might be setting focus to the same | ||
419 | // container that's already focused, so seat_set_focus is effectively a | ||
420 | // no op. We therefore need to send the IPC event and clean up the old | ||
421 | // workspace here. | ||
422 | ipc_event_workspace(active_ws, workspace, "focus"); | ||
423 | workspace_consider_destroy(active_ws); | ||
424 | } | ||
425 | seat_set_focus(seat, next); | 415 | seat_set_focus(seat, next); |
426 | arrange_workspace(workspace); | 416 | arrange_workspace(workspace); |
427 | cursor_send_pointer_motion(seat->cursor, 0, true); | 417 | cursor_send_pointer_motion(seat->cursor, 0, true); |
diff --git a/swaybar/bar.c b/swaybar/bar.c index 69069f40..ab307fd4 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c | |||
@@ -319,10 +319,14 @@ static bool bar_uses_output(struct swaybar *bar, const char *name) { | |||
319 | return false; | 319 | return false; |
320 | } | 320 | } |
321 | 321 | ||
322 | static void output_geometry(void *data, struct wl_output *output, int32_t x, | 322 | static void output_geometry(void *data, struct wl_output *wl_output, int32_t x, |
323 | int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, | 323 | int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, |
324 | const char *make, const char *model, int32_t transform) { | 324 | const char *make, const char *model, int32_t transform) { |
325 | // Who cares | 325 | struct swaybar_output *output = data; |
326 | output->subpixel = subpixel; | ||
327 | if (output->surface) { | ||
328 | render_frame(output->bar, output); | ||
329 | } | ||
326 | } | 330 | } |
327 | 331 | ||
328 | static void output_mode(void *data, struct wl_output *output, uint32_t flags, | 332 | static void output_mode(void *data, struct wl_output *output, uint32_t flags, |
diff --git a/swaybar/render.c b/swaybar/render.c index 26db80cb..9413dc57 100644 --- a/swaybar/render.c +++ b/swaybar/render.c | |||
@@ -495,6 +495,13 @@ void render_frame(struct swaybar *bar, struct swaybar_output *output) { | |||
495 | cairo_surface_t *recorder = cairo_recording_surface_create( | 495 | cairo_surface_t *recorder = cairo_recording_surface_create( |
496 | CAIRO_CONTENT_COLOR_ALPHA, NULL); | 496 | CAIRO_CONTENT_COLOR_ALPHA, NULL); |
497 | cairo_t *cairo = cairo_create(recorder); | 497 | cairo_t *cairo = cairo_create(recorder); |
498 | cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); | ||
499 | cairo_font_options_t *fo = cairo_font_options_create(); | ||
500 | cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL); | ||
501 | cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_SUBPIXEL); | ||
502 | cairo_font_options_set_subpixel_order(fo, to_cairo_subpixel_order(output->subpixel)); | ||
503 | cairo_set_font_options(cairo, fo); | ||
504 | cairo_font_options_destroy(fo); | ||
498 | cairo_save(cairo); | 505 | cairo_save(cairo); |
499 | cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); | 506 | cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); |
500 | cairo_paint(cairo); | 507 | cairo_paint(cairo); |
diff --git a/swaybar/status_line.c b/swaybar/status_line.c index 401bf6f6..48b43248 100644 --- a/swaybar/status_line.c +++ b/swaybar/status_line.c | |||
@@ -67,9 +67,13 @@ bool status_handle_readable(struct status_line *status) { | |||
67 | 67 | ||
68 | wl_list_init(&status->blocks); | 68 | wl_list_init(&status->blocks); |
69 | status->tokener = json_tokener_new(); | 69 | status->tokener = json_tokener_new(); |
70 | status->buffer_index = getdelim(&status->buffer, | 70 | read_bytes = getdelim(&status->buffer, &status->buffer_size, EOF, status->read); |
71 | &status->buffer_size, EOF, status->read); | 71 | if (read_bytes > 0) { |
72 | return i3bar_handle_readable(status); | 72 | status->buffer_index = read_bytes; |
73 | return i3bar_handle_readable(status); | ||
74 | } else { | ||
75 | return false; | ||
76 | } | ||
73 | } | 77 | } |
74 | 78 | ||
75 | wlr_log(WLR_DEBUG, "Using text protocol."); | 79 | wlr_log(WLR_DEBUG, "Using text protocol."); |
diff --git a/swaylock/main.c b/swaylock/main.c index 668a8742..c25c8eec 100644 --- a/swaylock/main.c +++ b/swaylock/main.c | |||
@@ -195,11 +195,15 @@ void damage_state(struct swaylock_state *state) { | |||
195 | } | 195 | } |
196 | } | 196 | } |
197 | 197 | ||
198 | static void handle_wl_output_geometry(void *data, struct wl_output *output, | 198 | static void handle_wl_output_geometry(void *data, struct wl_output *wl_output, |
199 | int32_t x, int32_t y, int32_t width_mm, int32_t height_mm, | 199 | int32_t x, int32_t y, int32_t width_mm, int32_t height_mm, |
200 | int32_t subpixel, const char *make, const char *model, | 200 | int32_t subpixel, const char *make, const char *model, |
201 | int32_t transform) { | 201 | int32_t transform) { |
202 | // Who cares | 202 | struct swaylock_surface *surface = data; |
203 | surface->subpixel = subpixel; | ||
204 | if (surface->state->run_display) { | ||
205 | damage_surface(surface); | ||
206 | } | ||
203 | } | 207 | } |
204 | 208 | ||
205 | static void handle_wl_output_mode(void *data, struct wl_output *output, | 209 | static void handle_wl_output_mode(void *data, struct wl_output *output, |
diff --git a/swaylock/render.c b/swaylock/render.c index 66c55965..fa8832bd 100644 --- a/swaylock/render.c +++ b/swaylock/render.c | |||
@@ -39,6 +39,13 @@ void render_frame(struct swaylock_surface *surface) { | |||
39 | } | 39 | } |
40 | 40 | ||
41 | cairo_t *cairo = surface->current_buffer->cairo; | 41 | cairo_t *cairo = surface->current_buffer->cairo; |
42 | cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); | ||
43 | cairo_font_options_t *fo = cairo_font_options_create(); | ||
44 | cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL); | ||
45 | cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_SUBPIXEL); | ||
46 | cairo_font_options_set_subpixel_order(fo, to_cairo_subpixel_order(surface->subpixel)); | ||
47 | cairo_set_font_options(cairo, fo); | ||
48 | cairo_font_options_destroy(fo); | ||
42 | cairo_identity_matrix(cairo); | 49 | cairo_identity_matrix(cairo); |
43 | 50 | ||
44 | cairo_save(cairo); | 51 | cairo_save(cairo); |