commit 9ea6375874aed8da333eeb1a6cc46af4edc4f9f5 Author: Kuoi Date: Sun Aug 21 20:14:34 2022 +0100 first commit diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0a83b51 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Ilia Bozhinov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..6b9d0a9 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# wayfire-plugins +A repository for Wayfire plugins which I use to tweak my own desktop diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..b319ff8 --- /dev/null +++ b/meson.build @@ -0,0 +1,34 @@ +project( + 'wf-roundedcorners', + 'c', + 'cpp', + version: '0.1', + license: 'MIT', + meson_version: '>=0.51.0', + default_options: [ + 'cpp_std=c++17', + 'c_std=c11', + 'warning_level=2', + 'werror=false', + ], +) + +wayfire = dependency('wayfire') +wlroots = dependency('wlroots') +wfconfig = dependency('wf-config') + +add_project_arguments(['-DWLR_USE_UNSTABLE'], language: ['cpp', 'c']) +add_project_arguments(['-DWAYFIRE_PLUGIN'], language: ['cpp', 'c']) +add_project_link_arguments(['-rdynamic'], language:'cpp') + +subdir('src') +subdir('metadata') + +summary = [ + '', + '----------------', + 'wf-roundcorner @0@'.format(meson.project_version()), + '----------------', + '' +] +message('\n'.join(summary)) diff --git a/src/meson.build b/src/meson.build new file mode 100644 index 0000000..0b85486 --- /dev/null +++ b/src/meson.build @@ -0,0 +1,3 @@ +rc = shared_module('rounded-corners', 'rounded-corners.cpp', + dependencies: [wayfire, wlroots], + install: true, install_dir: wayfire.get_variable(pkgconfig: 'plugindir')) diff --git a/src/rounded-corners.cpp b/src/rounded-corners.cpp new file mode 100644 index 0000000..e181077 --- /dev/null +++ b/src/rounded-corners.cpp @@ -0,0 +1,178 @@ +#include +#include +#include +#include +#include + +namespace +{ +const std::string vertex_source = R"( +#version 100 +attribute mediump vec2 position; +varying mediump vec2 fposition; + +uniform mat4 matrix; + +void main() { + gl_Position = matrix * vec4(position, 0.0, 1.0); + fposition = position; +})"; + +const std::string frag_source = R"( +#version 100 +@builtin_ext@ + +varying mediump vec2 fposition; +@builtin@ + +// Top left corner +uniform mediump vec2 top_left; + +// Top left corner with shadows included +uniform mediump vec2 full_top_left; + +// Bottom right corner +uniform mediump vec2 bottom_right; + +// Bottom right corner with shadows included +uniform mediump vec2 full_bottom_right; + +// Rounding radius +const mediump float radius = 20.0; + +void main() +{ + mediump vec2 corner_dist = min(fposition - top_left, bottom_right - fposition); + if (max(corner_dist.x, corner_dist.y) < radius) + { + if (distance(corner_dist, vec2(radius, radius)) > radius) + { + discard; + } + } + + highp vec2 uv = (fposition - full_top_left) / (full_bottom_right - full_top_left); + uv.y = 1.0 - uv.y; + gl_FragColor = get_pixel(uv); +})"; +} + +class rounded_corners_transformer_t : public wf::view_transformer_t +{ + public: + uint32_t get_z_order() override + { + return wf::TRANSFORMER_2D - 1; + } + + wf::region_t transform_opaque_region( + wf::geometry_t box, wf::region_t region) override + { + (void)box; + (void)region; + return {}; + } + + wf::pointf_t transform_point( + wf::geometry_t view, wf::pointf_t point) override + { + (void)view; + return point; + } + + wf::pointf_t untransform_point( + wf::geometry_t view, wf::pointf_t point) override + { + (void)view; + return point; + } + + wf::geometry_t get_bounding_box(wf::geometry_t bbox, wlr_box region) override + { + (void)bbox; + return wf::geometry_intersection(this->view->get_wm_geometry(), region); + } + + std::vector vertex_data; + void upload_data(wlr_box src_box) + { + auto geometry = view->get_wm_geometry(); + float x = geometry.x, y = geometry.y, + w = geometry.width, h = geometry.height; + + vertex_data = { + x, y + h, + x + w, y + h, + x + w, y, + x, y, + }; + program.attrib_pointer("position", 2, 0, vertex_data.data(), GL_FLOAT); + + program.uniform2f("top_left", x, y); + program.uniform2f("bottom_right", x + w, y + h); + program.uniform2f("full_top_left", src_box.x, src_box.y); + program.uniform2f("full_bottom_right", + src_box.x + src_box.width, src_box.y + src_box.height); + } + + void render_with_damage(wf::texture_t src_tex, wlr_box src_box, + const wf::region_t& damage, const wf::framebuffer_t& target_fb) override + { + OpenGL::render_begin(target_fb); + + program.use(src_tex.type); + program.set_active_texture(src_tex); + upload_data(src_box); + program.uniformMatrix4f("matrix", target_fb.get_orthographic_projection()); + + GL_CALL(glEnable(GL_BLEND)); + GL_CALL(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); + for (const auto& box : damage) + { + target_fb.logic_scissor(wlr_box_from_pixman_box(box)); + GL_CALL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); + } + + GL_CALL(glDisable(GL_BLEND)); + program.deactivate(); + OpenGL::render_end(); + } + + rounded_corners_transformer_t(wayfire_view view) + { + this->view = view; + + OpenGL::render_begin(); + program.compile(vertex_source, frag_source); + OpenGL::render_end(); + } + + virtual ~rounded_corners_transformer_t() + {} + + private: + wayfire_view view; + OpenGL::program_t program; +}; + +class wayfire_rounded_corners_t : public wf::plugin_interface_t +{ + public: + void init() override + { + output->connect_signal("view-mapped", &on_map); + } + + wf::signal_connection_t on_map = [=] (wf::signal_data_t *data) + { + auto view = wf::get_signaled_view(data); + // Ignore panels, backgrounds, etc. + if (view->role == wf::VIEW_ROLE_TOPLEVEL) + { + view->add_transformer( + std::make_unique(view)); + } + }; +}; + +DECLARE_WAYFIRE_PLUGIN(wayfire_rounded_corners_t);