diff options
-rw-r--r-- | include/container.h | 15 | ||||
-rw-r--r-- | include/render.h | 2 | ||||
-rw-r--r-- | sway/container.c | 3 | ||||
-rw-r--r-- | sway/handlers.c | 1 | ||||
-rw-r--r-- | sway/layout.c | 1 | ||||
-rw-r--r-- | sway/render.c | 111 |
6 files changed, 109 insertions, 24 deletions
diff --git a/include/container.h b/include/container.h index a96beab9..815898d7 100644 --- a/include/container.h +++ b/include/container.h | |||
@@ -36,6 +36,12 @@ enum swayc_layouts { | |||
36 | L_LAYOUTS, | 36 | L_LAYOUTS, |
37 | }; | 37 | }; |
38 | 38 | ||
39 | enum swayc_border_types { | ||
40 | B_NONE, /**< No border */ | ||
41 | B_PIXEL, /**< 1px border */ | ||
42 | B_NORMAL /**< Normal border with title bar */ | ||
43 | }; | ||
44 | |||
39 | /** | 45 | /** |
40 | * Stores information about a container. | 46 | * Stores information about a container. |
41 | * | 47 | * |
@@ -109,6 +115,15 @@ struct sway_container { | |||
109 | * If this container's children include a fullscreen view, this is that view. | 115 | * If this container's children include a fullscreen view, this is that view. |
110 | */ | 116 | */ |
111 | struct sway_container *fullscreen; | 117 | struct sway_container *fullscreen; |
118 | /** | ||
119 | * If this container is a view, this may be set to the window's decoration | ||
120 | * buffer (or NULL). | ||
121 | */ | ||
122 | unsigned char *border; | ||
123 | enum swayc_border_types border_type; | ||
124 | struct wlc_geometry border_geometry; | ||
125 | struct wlc_geometry presumed_geometry; | ||
126 | int border_thickness; | ||
112 | }; | 127 | }; |
113 | 128 | ||
114 | enum visibility_mask { | 129 | enum visibility_mask { |
diff --git a/include/render.h b/include/render.h index 19d3a52e..c3d1ca87 100644 --- a/include/render.h +++ b/include/render.h | |||
@@ -1,7 +1,9 @@ | |||
1 | #ifndef _SWAY_RENDER_H | 1 | #ifndef _SWAY_RENDER_H |
2 | #define _SWAY_RENDER_H | 2 | #define _SWAY_RENDER_H |
3 | #include <wlc/wlc.h> | 3 | #include <wlc/wlc.h> |
4 | #include "container.h" | ||
4 | 5 | ||
5 | void render_view_borders(wlc_handle view); | 6 | void render_view_borders(wlc_handle view); |
7 | void update_view_border(swayc_t *view); | ||
6 | 8 | ||
7 | #endif | 9 | #endif |
diff --git a/sway/container.c b/sway/container.c index 9330a3de..ac0d3231 100644 --- a/sway/container.c +++ b/sway/container.c | |||
@@ -22,8 +22,11 @@ static swayc_t *new_swayc(enum swayc_types type) { | |||
22 | c->gaps = -1; | 22 | c->gaps = -1; |
23 | c->layout = L_NONE; | 23 | c->layout = L_NONE; |
24 | c->type = type; | 24 | c->type = type; |
25 | c->border_type = B_PIXEL; // TODO: Load default from config | ||
26 | c->border_thickness = 2; | ||
25 | if (type != C_VIEW) { | 27 | if (type != C_VIEW) { |
26 | c->children = create_list(); | 28 | c->children = create_list(); |
29 | c->border_type = B_NONE; | ||
27 | } | 30 | } |
28 | return c; | 31 | return c; |
29 | } | 32 | } |
diff --git a/sway/handlers.c b/sway/handlers.c index dff682f5..47b649fd 100644 --- a/sway/handlers.c +++ b/sway/handlers.c | |||
@@ -357,6 +357,7 @@ static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geo | |||
357 | arrange_windows(view->parent, -1, -1); | 357 | arrange_windows(view->parent, -1, -1); |
358 | } | 358 | } |
359 | } | 359 | } |
360 | update_view_border(view); | ||
360 | } | 361 | } |
361 | 362 | ||
362 | static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { | 363 | static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { |
diff --git a/sway/layout.c b/sway/layout.c index d9c4598f..be898c58 100644 --- a/sway/layout.c +++ b/sway/layout.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include "focus.h" | 12 | #include "focus.h" |
13 | #include "output.h" | 13 | #include "output.h" |
14 | #include "ipc-server.h" | 14 | #include "ipc-server.h" |
15 | #include "render.h" | ||
15 | 16 | ||
16 | swayc_t root_container; | 17 | swayc_t root_container; |
17 | list_t *scratchpad; | 18 | list_t *scratchpad; |
diff --git a/sway/render.c b/sway/render.c index a5ba2f4c..9388c1d0 100644 --- a/sway/render.c +++ b/sway/render.c | |||
@@ -2,6 +2,8 @@ | |||
2 | #include <wlc/wlc-render.h> | 2 | #include <wlc/wlc-render.h> |
3 | #include <cairo/cairo.h> | 3 | #include <cairo/cairo.h> |
4 | #include <stdlib.h> | 4 | #include <stdlib.h> |
5 | #include <stdio.h> | ||
6 | #include "container.h" | ||
5 | 7 | ||
6 | void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { | 8 | void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { |
7 | cairo_set_source_rgba(cairo, | 9 | cairo_set_source_rgba(cairo, |
@@ -11,40 +13,101 @@ void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { | |||
11 | (color >> (0*8) & 0xFF) / 255.0); | 13 | (color >> (0*8) & 0xFF) / 255.0); |
12 | } | 14 | } |
13 | 15 | ||
14 | cairo_t *create_cairo_context(int width, int height, int channels, | 16 | cairo_t *create_border_buffer(swayc_t *view, struct wlc_geometry geo, |
15 | cairo_surface_t **surf, unsigned char **buf) { | 17 | cairo_surface_t **surface) { |
18 | const int channels = 4; | ||
16 | cairo_t *cr; | 19 | cairo_t *cr; |
17 | *buf = calloc(channels * width * height, sizeof(unsigned char)); | 20 | view->border_geometry = geo; |
18 | if (!*buf) { | 21 | view->border = calloc(channels * geo.size.w * geo.size.h, |
22 | sizeof(unsigned char)); | ||
23 | if (!view->border) { | ||
24 | sway_log(L_DEBUG, "Unable to allocate buffer"); | ||
19 | return NULL; | 25 | return NULL; |
20 | } | 26 | } |
21 | *surf = cairo_image_surface_create_for_data(*buf, CAIRO_FORMAT_ARGB32, | 27 | *surface = cairo_image_surface_create_for_data(view->border, |
22 | width, height, channels * width); | 28 | CAIRO_FORMAT_ARGB32, geo.size.w, geo.size.h, channels * geo.size.w); |
23 | if (cairo_surface_status(*surf) != CAIRO_STATUS_SUCCESS) { | 29 | if (cairo_surface_status(*surface) != CAIRO_STATUS_SUCCESS) { |
24 | free(*buf); | 30 | free(view->border); |
31 | view->border = NULL; | ||
32 | sway_log(L_DEBUG, "Unable to allocate surface"); | ||
25 | return NULL; | 33 | return NULL; |
26 | } | 34 | } |
27 | cr = cairo_create(*surf); | 35 | cr = cairo_create(*surface); |
28 | if (cairo_status(cr) != CAIRO_STATUS_SUCCESS) { | 36 | if (cairo_status(cr) != CAIRO_STATUS_SUCCESS) { |
29 | free(*buf); | 37 | cairo_surface_destroy(*surface); |
38 | free(view->border); | ||
39 | view->border = NULL; | ||
40 | sway_log(L_DEBUG, "Unable to create cairo context"); | ||
30 | return NULL; | 41 | return NULL; |
31 | } | 42 | } |
32 | return cr; | 43 | return cr; |
33 | } | 44 | } |
34 | 45 | ||
46 | void update_view_border(swayc_t *view) { | ||
47 | struct wlc_geometry geo; | ||
48 | wlc_view_get_visible_geometry(view->handle, &geo); | ||
49 | cairo_t *cr = NULL; | ||
50 | cairo_surface_t *surface = NULL; | ||
51 | |||
52 | if (view->border) { | ||
53 | free(view->border); | ||
54 | view->border = NULL; | ||
55 | } | ||
56 | |||
57 | switch (view->border_type) { | ||
58 | case B_NONE: | ||
59 | view->border_geometry = geo; | ||
60 | break; | ||
61 | case B_PIXEL: | ||
62 | geo.origin.x -= view->border_thickness; | ||
63 | geo.origin.y -= view->border_thickness; | ||
64 | geo.size.w += view->border_thickness * 2; | ||
65 | geo.size.h += view->border_thickness * 2; | ||
66 | if (geo.size.w <= 0 || geo.size.h <= 0) { | ||
67 | view->border = NULL; | ||
68 | break; | ||
69 | } | ||
70 | cr = create_border_buffer(view, geo, &surface); | ||
71 | if (!cr) { | ||
72 | break; | ||
73 | } | ||
74 | cairo_set_source_u32(cr, 0x0000FFFF); | ||
75 | cairo_paint(cr); | ||
76 | break; | ||
77 | case B_NORMAL: | ||
78 | // TODO | ||
79 | break; | ||
80 | } | ||
81 | if (surface) { | ||
82 | cairo_surface_flush(surface); | ||
83 | cairo_surface_destroy(surface); | ||
84 | } | ||
85 | if (cr) { | ||
86 | cairo_destroy(cr); | ||
87 | sway_log(L_DEBUG, "Created border for %p (%dx%d+%d,%d)", view, | ||
88 | geo.size.w, geo.size.h, geo.origin.x, geo.origin.y); | ||
89 | } | ||
90 | view->border_geometry = geo; | ||
91 | } | ||
92 | |||
35 | void render_view_borders(wlc_handle view) { | 93 | void render_view_borders(wlc_handle view) { |
36 | const int bw = 2; | 94 | swayc_t *c = swayc_by_handle(view); |
37 | unsigned char *surf_data; | 95 | if (!c || c->border_type == B_NONE) { |
38 | cairo_surface_t *surf; | 96 | return; |
39 | struct wlc_geometry geo = *wlc_view_get_geometry(view); | 97 | } |
40 | cairo_t *cr = create_cairo_context(geo.size.w + bw * 2, geo.size.h + bw * 2, 4, &surf, &surf_data); | 98 | struct wlc_geometry geo; |
41 | cairo_set_source_u32(cr, 0x0000FFFF); | 99 | wlc_view_get_visible_geometry(view, &geo); |
42 | cairo_paint(cr); | 100 | if (geo.size.w != c->presumed_geometry.size.w |
43 | geo.origin.x -= bw; | 101 | || geo.size.h != c->presumed_geometry.size.h |
44 | geo.origin.y -= bw; | 102 | || geo.origin.x != c->presumed_geometry.origin.x |
45 | geo.size.w += bw * 2; | 103 | || geo.origin.y != c->presumed_geometry.origin.y) { |
46 | geo.size.h += bw * 2; | 104 | update_view_border(c); |
47 | wlc_pixels_write(WLC_RGBA8888, &geo, surf_data); | 105 | c->presumed_geometry = geo; |
48 | cairo_destroy(cr); | 106 | } |
49 | free(surf_data); | 107 | if (c->border) { |
108 | geo = c->border_geometry; | ||
109 | sway_log(L_DEBUG, "Rendering border for %p (%dx%d+%d,%d)", c, | ||
110 | geo.size.w, geo.size.h, geo.origin.x, geo.origin.y); | ||
111 | wlc_pixels_write(WLC_RGBA8888, &c->border_geometry, c->border); | ||
112 | } | ||
50 | } | 113 | } |