├── meson_options.txt ├── SECURITY.md ├── compile-schemas.sh ├── dbus_interface.xml ├── org.wayland.compositor.dbus.gschema.xml ├── LICENSE ├── README.md ├── meson.build ├── wf-prop ├── dbus_scale_filter.hpp ├── wf-prop.cpp ├── dbus_interface.cpp ├── uncrustify.ini └── dbus_interface_backend.cpp /meson_options.txt: -------------------------------------------------------------------------------- 1 | option('build_wf_prop', type : 'boolean', value : true) 2 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | Only master branch get's security attention 3 | 4 | ## Reporting a Vulnerability 5 | send an email to admin@novoslinux.com 6 | -------------------------------------------------------------------------------- /compile-schemas.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Only compile schemas if DESTDIR isn't set 4 | [ ! -z "$DESTDIR" ] && exit 0 5 | 6 | exec glib-compile-schemas "$MESON_INSTALL_DESTDIR_PREFIX/$1" 7 | -------------------------------------------------------------------------------- /dbus_interface.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <_short>DBus Interface 5 | <_long>DBus Interface @ org.wayland.compositor 6 | Desktop 7 | 8 | 9 | -------------------------------------------------------------------------------- /org.wayland.compositor.dbus.gschema.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | false 6 | geometry-signal 7 | geometry-signal 8 | 9 | 10 | "" 11 | Command that runs on session startup 12 | Command that runs on session startup 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Damian Ivanov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DBus Wayfire plugin 2 | 3 | Authors: Damian Ivanov 4 | 5 | Contributors: https://github.com/damianatorrpm/wayfire-plugin_dbus_interface/graphs/contributors 6 | 7 | ### Installation 8 | - Install (wayfire-plugins-extra)[https://github.com/WayfireWM/wayfire-plugins-extra] 9 | - Build & install the plugin and wf-prop: `meson build && ninja -C build && sudo meson install -C build` 10 | - Enable `glib-main-loop` and `dbus_interface` in your wayfire.ini 11 | 12 | If one of the plugins isn't loaded (check wayfire's debug output), make sure the plugin was installed to the correct path. 13 | 14 | ### Coding style 15 | * uncrustify.ini in the repo 16 | * follow the style used 17 | * using 'auto' is strongly discouraged 18 | 19 | ### wf-prop 20 | * wf-prop l / wf-prop list for a detailed list of all taskmanger relevant (toplevel) windows. 21 | * wf-prop + click on a window to query details about that window 22 | 23 | ### other examples 24 | 25 | * To continuously monitor for signals 26 | >gdbus monitor --session --dest org.wayland.compositor --object-path /org/wayland/compositor" 27 | 28 | * To query taskamanager relevant windows 29 | >gdbus call --session --dest org.wayland.compositor --object-path /org/wayland/compositor --method org.wayland.compositor.query_view_vector_taskman_ids 30 | 31 | * To fullscreen a window (query the id you want from the properties) 32 | >gdbus call --session --dest org.wayland.compositor --object-path /org/wayland/compositor --method org.wayland.compositor.fullscreen_view $id 1 33 | 34 | * To restore previous state from fullscreen 35 | >gdbus call --session --dest org.wayland.compositor --object-path /org/wayland/compositor --method org.wayland.compositor.fullscreen_view $id 0 36 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project( 2 | 'wayfire-plugin-dbus_interface', 3 | 'c', 4 | 'cpp', 5 | version: '0.3', 6 | license: 'MIT', 7 | meson_version: '>=0.51.0', 8 | default_options: [ 9 | 'cpp_std=c++17', 10 | 'c_std=c17', 11 | 'werror=false', 12 | ], 13 | ) 14 | 15 | gio = dependency('gio-2.0') 16 | giomm = dependency('giomm-2.4', required : get_option('build_wf_prop')) 17 | 18 | wayfire = dependency('wayfire', required : true) 19 | wlroots = dependency('wlroots') 20 | wfconfig = dependency('wf-config') 21 | glib = dependency('glib-2.0') 22 | xcb = dependency('xcb') 23 | xcbres = dependency('xcb-res') 24 | 25 | add_project_arguments(['-DWLR_USE_UNSTABLE'], language: ['cpp', 'c']) 26 | add_project_arguments(['-DWAYFIRE_PLUGIN'], language: ['cpp', 'c']) 27 | add_project_arguments(['-Wno-unused-parameter'], language: 'cpp') 28 | add_project_link_arguments(['-rdynamic'], language:'cpp') 29 | 30 | 31 | 32 | ######################### Finish ########################### 33 | schemas_dir = 'share/glib-2.0/schemas' 34 | install_data('org.wayland.compositor.dbus.gschema.xml', 35 | install_dir: join_paths(get_option('prefix'), schemas_dir)) 36 | meson.add_install_script('compile-schemas.sh', schemas_dir) 37 | 38 | pms = shared_module('dbus_interface', 'dbus_interface.cpp', 39 | dependencies: [wayfire, wlroots, gio, xcb, xcbres], 40 | install: true, install_dir: wayfire.get_variable(pkgconfig: 'plugindir'), 41 | cpp_args : ['-Wno-write-strings', '-Wno-unused-parameter', '-Wno-format-security']) 42 | install_data('dbus_interface.xml', install_dir: wayfire.get_variable(pkgconfig: 'metadatadir')) 43 | 44 | if get_option('build_wf_prop') 45 | executable('wf-prop', 'wf-prop.cpp', 46 | dependencies: [gio, giomm], 47 | install: true, 48 | ) 49 | endif 50 | 51 | summary = [ 52 | '', 53 | '----------------', 54 | 'wayfire-plugins-dbus_interface @0@'.format(meson.project_version()), 55 | 'build wf-prop: @0@'.format(get_option('build_wf_prop')), 56 | '----------------', 57 | '' 58 | ] 59 | message('\n'.join(summary)) 60 | -------------------------------------------------------------------------------- /wf-prop: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | busctl --user call org.wayland.compositor /org/wayland/compositor org.wayland.compositor enable_property_mode b true 4 | ( gdbus monitor --session --dest org.wayland.compositor --object-path /org/wayland/compositor & echo $! >&3 ) 3>gdbus_pid | 5 | 6 | while read -r line; do 7 | if [[ $line == *"/org/wayland/compositor: org.wayland.compositor.view_pressed (uint32"* ]]; then 8 | busctl --user call org.wayland.compositor /org/wayland/compositor org.wayland.compositor enable_property_mode b false 9 | VIEW_ID=$(echo $line| cut -d'2' -f 2) 10 | VIEW_ID="${VIEW_ID%,*}" 11 | printf "\n\n" 12 | echo app id: $(gdbus call --session --dest org.wayland.compositor --object-path /org/wayland/compositor --method org.wayland.compositor.query_view_app_id 0) 13 | echo title: $(gdbus call --session --dest org.wayland.compositor --object-path /org/wayland/compositor --method org.wayland.compositor.query_view_title 0) 14 | echo PID/UID/GID: $(gdbus call --session --dest org.wayland.compositor --object-path /org/wayland/compositor --method org.wayland.compositor.query_view_credentials 0) 15 | echo active: $(gdbus call --session --dest org.wayland.compositor --object-path /org/wayland/compositor --method org.wayland.compositor.query_view_active 0) 16 | echo minimized: $(gdbus call --session --dest org.wayland.compositor --object-path /org/wayland/compositor --method org.wayland.compositor.query_view_minimized 0) 17 | echo maximized: $(gdbus call --session --dest org.wayland.compositor --object-path /org/wayland/compositor --method org.wayland.compositor.query_view_maximized 0) 18 | echo fullscreen: $(gdbus call --session --dest org.wayland.compositor --object-path /org/wayland/compositor --method org.wayland.compositor.query_view_fullscreen 0) 19 | echo above: $(gdbus call --session --dest org.wayland.compositor --object-path /org/wayland/compositor --method org.wayland.compositor.query_view_above 0) 20 | echo workspaces: $(gdbus call --session --dest org.wayland.compositor --object-path /org/wayland/compositor --method org.wayland.compositor.query_view_workspaces 0) 21 | echo role: $(gdbus call --session --dest org.wayland.compositor --object-path /org/wayland/compositor --method org.wayland.compositor.query_view_role 0) 22 | echo ****XWayland Information - no data means this native wayland window*** 23 | # Extend with properties you like 24 | # query_view_xwayland_atom_string for string 25 | # query_view_xwayland_atom_cardinal for int 26 | echo WID: $(gdbus call --session --dest org.wayland.compositor --object-path /org/wayland/compositor --method org.wayland.compositor.query_view_xwayland_wid 0) 27 | echo _NET_WM_NAME: $(gdbus call --session --dest org.wayland.compositor --object-path /org/wayland/compositor --method org.wayland.compositor.query_view_xwayland_atom_string 0 _NET_WM_NAME) 28 | kill $( 4 | * 5 | * dbus_scale_filter.hpp -- helper class to filter scaled apps by dbus 6 | *********************************************************************/ 7 | 8 | #ifndef DBUS_SCALE_FILTER_HPP 9 | #define DBUS_SCALE_FILTER_HPP 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | /* one instance of each of this class is added to each output */ 18 | class dbus_scale_filter : public wf::custom_data_t 19 | { 20 | protected: 21 | std::string filter; 22 | 23 | static unsigned char 24 | transform (unsigned char c) 25 | { 26 | if (std::isspace(c)) 27 | { 28 | return ' '; 29 | } 30 | 31 | return (c <= 127) ? (unsigned char)std::tolower(c) : c; 32 | } 33 | 34 | bool 35 | should_show_view (wayfire_view v) 36 | { 37 | if (filter.empty()) 38 | { 39 | return true; 40 | } 41 | 42 | std::string app_id = v->get_app_id(); 43 | std::transform(app_id.begin(), app_id.end(), app_id.begin(), transform); 44 | 45 | return filter == app_id; 46 | } 47 | 48 | wf::signal_connection_t view_filter{[this] (wf::signal_data_t* data) 49 | { 50 | auto signal = static_cast (data); 51 | scale_filter_views(signal, [this] (wayfire_view v) 52 | { 53 | return !should_show_view(v); 54 | }); 55 | } 56 | }; 57 | 58 | wf::signal_connection_t scale_end{[this] (auto) 59 | { 60 | filter.clear(); 61 | } 62 | }; 63 | 64 | void 65 | connect_signals (wf::output_t* output) 66 | { 67 | output->connect_signal("scale-filter", &view_filter); 68 | output->connect_signal("scale-end", &scale_end); 69 | } 70 | 71 | public: 72 | static nonstd::observer_ptr 73 | get (wf::output_t* output) 74 | { 75 | auto ret = output->get_data (); 76 | if (ret) 77 | { 78 | return ret; 79 | } 80 | 81 | dbus_scale_filter* new_ret = new dbus_scale_filter(); 82 | output->store_data(std::unique_ptr (new_ret)); 83 | new_ret->connect_signals(output); 84 | 85 | return new_ret; 86 | } 87 | 88 | void 89 | set_filter (const std::string& new_filter) 90 | { 91 | filter = new_filter; 92 | std::transform(filter.begin(), filter.end(), filter.begin(), transform); 93 | } 94 | 95 | void 96 | set_filter (std::string&& new_filter) 97 | { 98 | filter = std::move(new_filter); 99 | std::transform(filter.begin(), filter.end(), filter.begin(), transform); 100 | } 101 | 102 | // unload all instances of filters attached to all outputs 103 | static void 104 | unload () 105 | { 106 | wf::compositor_core_t& core = wf::get_core(); 107 | for (auto output : core.output_layout->get_outputs()) 108 | { 109 | output->erase_data (); 110 | } 111 | } 112 | }; 113 | 114 | #endif -------------------------------------------------------------------------------- /wf-prop.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************* 2 | * This file is licensed under the MIT license. 3 | * Copyright (C) 2019 - 2020 Damian Ivanov 4 | ********************************************************************/ 5 | 6 | #define DBUS_ID "org.wayland.compositor" 7 | #define DBUS_PATH "/org/wayland/compositor" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | using DBusConnection = Glib::RefPtr; 19 | using DBusProxy = Glib::RefPtr; 20 | 21 | /* 22 | * Print a list of query_view_taskman_ids and output them as 23 | * 24 | */ 25 | static gboolean list = FALSE; 26 | static DBusConnection connection; 27 | static DBusProxy proxy; 28 | 29 | static std::vector<std::pair<int, int>> 30 | query_view_workspaces (guint view_id) 31 | { 32 | std::vector<std::pair<int, int>> workspaces; 33 | 34 | GError* error = NULL; 35 | GVariant* tmp = NULL; 36 | int x, y; 37 | 38 | tmp = g_dbus_proxy_call_sync(proxy->gobj(), "query_view_workspaces", 39 | g_variant_new("(u)", view_id), 40 | G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); 41 | 42 | g_assert_no_error(error); 43 | 44 | GVariantIter iter; 45 | GVariantIter iter2; 46 | GVariantIter iter3; 47 | GVariant* child; 48 | GVariant* cchild; 49 | GVariant* ccchild; 50 | 51 | g_variant_iter_init(&iter, tmp); 52 | 53 | while ((child = g_variant_iter_next_value(&iter))) 54 | { 55 | g_variant_iter_init(&iter2, child); 56 | while ((cchild = g_variant_iter_next_value(&iter2))) 57 | { 58 | g_variant_get_child(cchild, 0, "i", &x); 59 | g_variant_get_child(cchild, 1, "i", &y); 60 | g_debug("view workspaces: %i %i", x, y); 61 | workspaces.push_back(std::make_pair(x, y)); 62 | } 63 | } 64 | 65 | g_variant_unref(tmp); 66 | 67 | if (workspaces.size() == 0) { 68 | g_warning("No workspaces found for view: %u", view_id); 69 | } 70 | 71 | return workspaces; 72 | } 73 | 74 | static uint 75 | query_view_output (guint view_id) 76 | { 77 | GError* error = NULL; 78 | GVariant* tmp = NULL; 79 | uint value = 0; 80 | tmp = g_dbus_proxy_call_sync(proxy->gobj(), "query_view_output", 81 | g_variant_new("(u)", view_id), 82 | G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); 83 | g_assert_no_error(error); 84 | g_variant_get(tmp, "(u)", &value); 85 | g_variant_unref(tmp); 86 | 87 | return value; 88 | } 89 | 90 | static int 91 | query_view_below_view (guint view_id) 92 | { 93 | GVariant* tmp = NULL; 94 | int value = 0; 95 | tmp = g_dbus_proxy_call_sync(proxy->gobj(), "query_view_below_view", 96 | g_variant_new("(u)", view_id), 97 | G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL); 98 | g_variant_get(tmp, "(i)", &value); 99 | g_variant_unref(tmp); 100 | 101 | return value; 102 | } 103 | 104 | static int 105 | query_view_above_view (guint view_id) 106 | { 107 | GVariant* tmp = NULL; 108 | int value = 0; 109 | tmp = g_dbus_proxy_call_sync(proxy->gobj(), "query_view_above_view", 110 | g_variant_new("(u)", view_id), 111 | G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL); 112 | g_variant_get(tmp, "(i)", &value); 113 | g_variant_unref(tmp); 114 | 115 | return value; 116 | } 117 | 118 | static gboolean 119 | query_view_minimized (guint view_id) 120 | { 121 | GError* error = NULL; 122 | GVariant* tmp = NULL; 123 | gboolean value; 124 | tmp = g_dbus_proxy_call_sync(proxy->gobj(), "query_view_minimized", 125 | g_variant_new("(u)", view_id), 126 | G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); 127 | 128 | g_assert_no_error(error); 129 | g_variant_get(tmp, "(b)", &value); 130 | g_variant_unref(tmp); 131 | 132 | return value; 133 | } 134 | 135 | static gboolean 136 | query_view_maximized (guint view_id) 137 | { 138 | GError* error = NULL; 139 | GVariant* tmp = NULL; 140 | gboolean value; 141 | tmp = g_dbus_proxy_call_sync(proxy->gobj(), "query_view_maximized", 142 | g_variant_new("(u)", view_id), 143 | G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); 144 | 145 | g_assert_no_error(error); 146 | g_variant_get(tmp, "(b)", &value); 147 | g_variant_unref(tmp); 148 | 149 | return value; 150 | } 151 | 152 | static gboolean 153 | query_view_fullscreen (guint view_id) 154 | { 155 | GError* error = NULL; 156 | GVariant* tmp = NULL; 157 | gboolean value; 158 | tmp = g_dbus_proxy_call_sync(proxy->gobj(), "query_view_fullscreen", 159 | g_variant_new("(u)", view_id), 160 | G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); 161 | 162 | g_assert_no_error(error); 163 | g_variant_get(tmp, "(b)", &value); 164 | g_variant_unref(tmp); 165 | 166 | return value; 167 | } 168 | 169 | static gchar* 170 | query_output_name (guint output_id) 171 | { 172 | GError* error = NULL; 173 | GVariant* tmp = NULL; 174 | gchar* value = NULL; 175 | 176 | tmp = g_dbus_proxy_call_sync(proxy->gobj(), "query_output_name", 177 | g_variant_new("(u)", output_id), 178 | G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); 179 | g_assert_no_error(error); 180 | g_variant_get(tmp, "(s)", &value); 181 | g_variant_unref(tmp); 182 | 183 | return value; 184 | } 185 | 186 | static std::pair<int, int> 187 | query_output_workspace (guint output_id) 188 | { 189 | GError* error = NULL; 190 | GVariant* tmp = NULL; 191 | uint x = 0; 192 | uint y = 0; 193 | 194 | tmp = g_dbus_proxy_call_sync(proxy->gobj(), "query_output_workspace", 195 | g_variant_new("(u)", output_id), 196 | G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); 197 | g_assert_no_error(error); 198 | g_variant_get(tmp, "(uu)", &x, &y); 199 | g_variant_unref(tmp); 200 | 201 | return std::pair<int, int>{x, y}; 202 | } 203 | 204 | static uint 205 | query_active_output () 206 | { 207 | GError* error = NULL; 208 | GVariant* tmp = NULL; 209 | uint value = 0; 210 | 211 | tmp = g_dbus_proxy_call_sync(proxy->gobj(), "query_active_output", NULL, 212 | G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); 213 | g_assert_no_error(error); 214 | g_variant_get(tmp, "(u)", &value); 215 | g_variant_unref(tmp); 216 | 217 | return value; 218 | } 219 | 220 | static uint 221 | query_view_role (uint view_id) 222 | { 223 | GError* error = NULL; 224 | GVariant* tmp = NULL; 225 | uint value = 0; 226 | 227 | tmp = g_dbus_proxy_call_sync(proxy->gobj(), "query_view_role", 228 | g_variant_new("(u)", view_id), 229 | G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); 230 | g_assert_no_error(error); 231 | g_variant_get(tmp, "(u)", &value); 232 | g_variant_unref(tmp); 233 | 234 | return value; 235 | } 236 | 237 | static uint 238 | query_view_group_leader (uint view_id) 239 | { 240 | GError* error = NULL; 241 | GVariant* tmp = NULL; 242 | uint value; 243 | 244 | tmp = g_dbus_proxy_call_sync(proxy->gobj(), "query_view_group_leader", 245 | g_variant_new("(u)", view_id), 246 | G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); 247 | g_assert_no_error(error); 248 | g_variant_get(tmp, "(u)", &value); 249 | g_variant_unref(tmp); 250 | 251 | return value; 252 | } 253 | 254 | static gchar* 255 | query_view_app_id (uint view_id) 256 | { 257 | GError* error = NULL; 258 | GVariant* tmp = NULL; 259 | gchar* value = NULL; 260 | 261 | tmp = g_dbus_proxy_call_sync(proxy->gobj(), "query_view_app_id", 262 | g_variant_new("(u)", view_id), 263 | G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); 264 | g_assert_no_error(error); 265 | g_variant_get(tmp, "(s)", &value); 266 | g_variant_unref(tmp); 267 | 268 | return value; 269 | } 270 | 271 | static gchar* 272 | query_view_app_id_gtk_shell (uint view_id) 273 | { 274 | GError* error = NULL; 275 | GVariant* tmp = NULL; 276 | gchar* value = NULL; 277 | 278 | tmp = g_dbus_proxy_call_sync(proxy->gobj(), "query_view_app_id_gtk_shell", 279 | g_variant_new("(u)", view_id), 280 | G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); 281 | g_assert_no_error(error); 282 | g_variant_get(tmp, "(s)", &value); 283 | g_variant_unref(tmp); 284 | 285 | return value; 286 | } 287 | 288 | static gchar* 289 | query_view_app_id_xwayland_net_wm_name (uint view_id) 290 | { 291 | GError* error = NULL; 292 | GVariant* tmp = NULL; 293 | gchar* value = NULL; 294 | 295 | tmp = g_dbus_proxy_call_sync( 296 | proxy->gobj(), "query_view_app_id_xwayland_net_wm_name", 297 | g_variant_new("(u)", view_id), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); 298 | g_assert_no_error(error); 299 | g_variant_get(tmp, "(s)", &value); 300 | g_variant_unref(tmp); 301 | 302 | return value; 303 | } 304 | 305 | static gchar* 306 | query_view_title (uint view_id) 307 | { 308 | GError* error = NULL; 309 | GVariant* tmp = NULL; 310 | gchar* value = NULL; 311 | 312 | tmp = g_dbus_proxy_call_sync(proxy->gobj(), "query_view_title", 313 | g_variant_new("(u)", view_id), 314 | G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); 315 | g_assert_no_error(error); 316 | g_variant_get(tmp, "(s)", &value); 317 | g_variant_unref(tmp); 318 | 319 | return value; 320 | } 321 | 322 | static int 323 | query_view_xwayland_atom_cardinal (uint view_id, const char* val) 324 | { 325 | GError* error = NULL; 326 | GVariant* tmp = NULL; 327 | int value; 328 | 329 | tmp = 330 | g_dbus_proxy_call_sync(proxy->gobj(), "query_view_xwayland_atom_cardinal", 331 | g_variant_new("(us)", view_id, val), 332 | G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); 333 | g_assert_no_error(error); 334 | g_variant_get(tmp, "(u)", &value); 335 | g_variant_unref(tmp); 336 | 337 | return value; 338 | } 339 | 340 | static gboolean 341 | query_view_active (guint view_id) 342 | { 343 | GError* error = NULL; 344 | GVariant* tmp = NULL; 345 | gboolean value; 346 | tmp = g_dbus_proxy_call_sync(proxy->gobj(), "query_view_active", 347 | g_variant_new("(u)", view_id), 348 | G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); 349 | 350 | g_assert_no_error(error); 351 | g_variant_get(tmp, "(b)", &value); 352 | g_variant_unref(tmp); 353 | 354 | return value; 355 | } 356 | 357 | static uint 358 | query_view_xwayland_wid (uint view_id) 359 | { 360 | GError* error = NULL; 361 | GVariant* tmp = NULL; 362 | uint value = 0; 363 | 364 | tmp = g_dbus_proxy_call_sync(proxy->gobj(), "query_view_xwayland_wid", 365 | g_variant_new("(u)", view_id), 366 | G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); 367 | g_assert_no_error(error); 368 | g_variant_get(tmp, "(u)", &value); 369 | g_variant_unref(tmp); 370 | 371 | return value; 372 | } 373 | 374 | static void 375 | print_view_data (guint view_id) 376 | { 377 | // XXX: is there any point to free memory in such a short lived program? 378 | gchar* app_id = query_view_app_id(view_id); 379 | gchar* app_id_gtk = query_view_app_id_gtk_shell(view_id); 380 | gchar* title = query_view_title(view_id); 381 | gboolean minimized = query_view_minimized(view_id); 382 | gboolean maximized = query_view_maximized(view_id); 383 | gboolean fullscreened = query_view_fullscreen(view_id); 384 | gboolean active = query_view_active(view_id); 385 | guint above_id = query_view_above_view(view_id); 386 | guint below_id = query_view_below_view(view_id); 387 | gchar* above_app_id = query_view_app_id(above_id); 388 | gchar* below_app_id = query_view_app_id(below_id); 389 | guint output = query_view_output(view_id); 390 | gchar* output_name = query_output_name(output); 391 | guint xwid = query_view_xwayland_wid(view_id); 392 | guint role = query_view_role(view_id); 393 | guint group_leader = query_view_group_leader(view_id); 394 | 395 | std::vector<std::pair<int, int>> workspaces = query_view_workspaces(view_id); 396 | GError* error = NULL; 397 | GVariant* tmp = NULL; 398 | gint pid; 399 | guint uid; 400 | guint gid; 401 | tmp = g_dbus_proxy_call_sync(proxy->gobj(), "query_view_credentials", 402 | g_variant_new("(u)", view_id), 403 | G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); 404 | g_assert_no_error(error); 405 | g_variant_get(tmp, "(iuu)", &pid, &uid, &gid); 406 | g_variant_unref(tmp); 407 | 408 | g_print("View Id: %u\n", view_id); 409 | g_print("App Id: [%s, %s]\n", app_id, app_id_gtk); 410 | g_print("Title: %s\n", title); 411 | if (role == 1) { 412 | g_print("Role: %s\n", "Toplevel Window"); 413 | } 414 | else 415 | if (role == 2) 416 | { 417 | g_print("Role: %s\n", "Desktop Environment"); 418 | } 419 | else 420 | if (role == 3) 421 | { 422 | g_print("Role: %s\n", "Unmanaged Window"); 423 | } 424 | else 425 | { 426 | g_print("Role: %s\n", "Unknown"); 427 | } 428 | 429 | g_print("Group Leader: %i\n", group_leader); 430 | g_print("Process id: %i\n", pid); 431 | g_print("User id: %u\n", uid); 432 | g_print("Group id: %u\n", gid); 433 | g_print("Active: %s\n", (active ? "True" : "False")); 434 | g_print("Minimized: %s\n", (minimized ? "True" : "False")); 435 | g_print("Maximized: %s\n", (maximized ? "True" : "False")); 436 | g_print("Fullscreen: %s\n", (fullscreened ? "True" : "False")); 437 | g_print("Workspaces: "); 438 | 439 | for (auto it = workspaces.begin(); it != workspaces.end(); ++it) 440 | { 441 | std::pair<int, int> ws = *it; 442 | g_print("[%i, %i]", ws.first, ws.second); 443 | } 444 | 445 | g_print("\n"); 446 | g_print("Output: [%u] %s\n", output, output_name); 447 | g_print("Above this view: [%i] %s\n", above_id, 448 | (above_id != -1 ? above_app_id : "None")); 449 | g_print("Below this view: [%i] %s\n", below_id, 450 | (below_id != -1 ? below_app_id : "None")); 451 | 452 | if (xwid == 0) { 453 | g_print("\n == This is a native wayland window ==\n"); 454 | } 455 | else 456 | { 457 | g_print("\n == This is a xwayland window ==\n\n"); 458 | std::stringstream stream; 459 | stream << std::hex << xwid; 460 | std::string result("0x" + stream.str()); 461 | g_print("X Window id: %s\n", result.c_str()); 462 | g_print("Run xwininfo -all -id %s and/or xprop -id %s for more " 463 | "information.\n", 464 | result.c_str(), result.c_str()); 465 | } 466 | } 467 | 468 | static void 469 | on_signal (GDBusConnection* connection, const gchar* sender_name, 470 | const gchar* object_path, const gchar* interface_name, 471 | const gchar* signal_name, GVariant* parameters, 472 | gpointer user_data) 473 | { 474 | uint view_id; 475 | g_variant_get(parameters, "(u)", &view_id); 476 | uint _tmp = query_view_role(view_id); 477 | 478 | if ((_tmp != 1) && (_tmp != 2)) 479 | { 480 | g_print("This surface is part of the desktop/compositor. Role: %u\n", _tmp); 481 | g_print("Please select another one.\n"); 482 | 483 | return; 484 | } 485 | 486 | g_dbus_proxy_call_sync(proxy->gobj(), "enable_property_mode", 487 | g_variant_new("(b)", FALSE), G_DBUS_CALL_FLAGS_NONE, 488 | -1, NULL, NULL); 489 | print_view_data(view_id); 490 | exit(0); 491 | } 492 | 493 | static GOptionEntry entries [] = { 494 | {"list", 'l', 0, G_OPTION_ARG_NONE, &list, 495 | "List taskmanager related entries and exit", 496 | NULL}, 497 | {NULL} 498 | }; 499 | 500 | int 501 | main (int argc, char* argv []) 502 | { 503 | GError* error = NULL; 504 | GOptionContext* context; 505 | GMainLoop* loop; 506 | 507 | context = g_option_context_new("- get window properties"); 508 | g_option_context_add_main_entries(context, entries, NULL); 509 | 510 | if (!g_option_context_parse(context, &argc, &argv, &error)) { 511 | g_print("%s\n", error->message); 512 | exit(1); 513 | } 514 | 515 | g_option_context_free(context); 516 | loop = g_main_loop_new(NULL, FALSE); 517 | 518 | Glib::RefPtr<Gio::Application> app = Gio::Application::create( 519 | "org.wayfire.wf-prop", Gio::APPLICATION_FLAGS_NONE); 520 | 521 | auto cancellable = Gio::Cancellable::create(); 522 | connection = 523 | Gio::DBus::Connection::get_sync(Gio::DBus::BUS_TYPE_SESSION, cancellable); 524 | 525 | // g_main_loop_run(loop); 526 | 527 | if (!connection) { 528 | g_error("Failed to connect to dbus"); 529 | 530 | return false; 531 | } 532 | 533 | proxy = 534 | Gio::DBus::Proxy::create_sync(connection, DBUS_ID, DBUS_PATH, DBUS_ID); 535 | if (!proxy) { 536 | g_error("Failed to connect to dbus interface"); 537 | 538 | return false; 539 | } 540 | 541 | for (char** arg = argv; *arg; arg++) 542 | { 543 | if ((g_strcmp0(*arg, "l") == 0) || (g_strcmp0(*arg, "list") == 0)) { 544 | GVariant* value; 545 | GError* error = NULL; 546 | 547 | value = g_dbus_proxy_call_sync(proxy->gobj(), 548 | "query_view_vector_taskman_ids", NULL, 549 | G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); 550 | g_assert_no_error(error); 551 | GVariantIter iter; 552 | GVariantIter iter2; 553 | GVariant* child; 554 | GVariant* cchild; 555 | 556 | g_variant_iter_init(&iter, value); 557 | while ((child = g_variant_iter_next_value(&iter))) 558 | { 559 | g_variant_iter_init(&iter2, child); 560 | while ((cchild = g_variant_iter_next_value(&iter2))) 561 | { 562 | g_print("***************************************\n"); 563 | print_view_data(g_variant_get_uint32(cchild)); 564 | g_print("***************************************\n\n"); 565 | } 566 | } 567 | 568 | g_dbus_proxy_call_sync(proxy->gobj(), "enable_property_mode", 569 | g_variant_new("(b)", FALSE), 570 | G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); 571 | g_assert_no_error(error); 572 | exit(0); 573 | } 574 | } 575 | 576 | g_dbus_connection_signal_subscribe( 577 | connection->gobj(), DBUS_ID, DBUS_ID, "view_pressed", DBUS_PATH, 578 | NULL, /* match rule */ 579 | G_DBUS_SIGNAL_FLAGS_NONE, on_signal, NULL, /* user data */ 580 | NULL); 581 | 582 | g_dbus_proxy_call_sync(proxy->gobj(), "enable_property_mode", 583 | g_variant_new("(b)", TRUE), G_DBUS_CALL_FLAGS_NONE, -1, 584 | NULL, &error); 585 | g_main_loop_run(loop); 586 | } 587 | -------------------------------------------------------------------------------- /dbus_interface.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************* 2 | * This file is licensed under the MIT license. 3 | * Copyright (C) 2019 - 2020 Damian Ivanov <damianatorrpm@gmail.com> 4 | ********************************************************************/ 5 | 6 | #define HAS_CUSTOM 0 7 | #define DBUS_PLUGIN_DEBUG TRUE 8 | #define DBUS_PLUGIN_WARN TRUE 9 | 10 | extern "C" { 11 | #include <sys/socket.h> 12 | #include <sys/types.h> 13 | }; 14 | 15 | #include <gio/gio.h> 16 | #include <algorithm> 17 | #include <charconv> 18 | #include <cmath> 19 | #include <iostream> 20 | #include <linux/input.h> 21 | #include <string> 22 | 23 | #include <wayfire/compositor-view.hpp> 24 | #include <wayfire/core.hpp> 25 | #include <wayfire/debug.hpp> 26 | #include <wayfire/input-device.hpp> 27 | #include <wayfire/option-wrapper.hpp> 28 | #include <wayfire/output-layout.hpp> 29 | #include <wayfire/output.hpp> 30 | #include <wayfire/plugin.hpp> 31 | #include <wayfire/plugins/common/view-change-viewport-signal.hpp> 32 | #include <wayfire/render-manager.hpp> 33 | #include <wayfire/signal-definitions.hpp> 34 | #include <wayfire/singleton-plugin.hpp> 35 | #include <wayfire/util.hpp> 36 | #include <wayfire/util/duration.hpp> 37 | #include <wayfire/util/log.hpp> 38 | #include <wayfire/view.hpp> 39 | #include <wayfire/workspace-manager.hpp> 40 | 41 | #include <wayfire/signal-definitions.hpp> 42 | 43 | #include "dbus_interface_backend.cpp" 44 | gboolean geometry_signal = FALSE; 45 | 46 | static void 47 | settings_changed (GSettings* settings, const gchar* key, 48 | gpointer user_data) 49 | { 50 | if (g_strcmp0(key, "geometry-signal") == 0) { 51 | geometry_signal = g_settings_get_boolean(settings, "geometry-signal"); 52 | } 53 | else 54 | { 55 | g_warning("No such settings %s", key); 56 | } 57 | } 58 | 59 | class dbus_interface_t 60 | { 61 | public: 62 | /************* Connect all signals for already existing objects 63 | * **************/ 64 | dbus_interface_t() 65 | { 66 | #ifdef DBUS_PLUGIN_DEBUG 67 | LOG(wf::log::LOG_LEVEL_DEBUG, "Loading DBus Plugin"); 68 | #endif 69 | 70 | settings = g_settings_new("org.wayland.compositor.dbus"); 71 | for (wf::output_t* output : wf_outputs) 72 | { 73 | grab_interfaces[output] = 74 | std::make_unique<wf::plugin_grab_interface_t> (output); 75 | grab_interfaces[output]->name = "dbus"; 76 | grab_interfaces[output]->capabilities = wf::CAPABILITY_GRAB_INPUT; 77 | output->connect_signal("view-mapped", &output_view_added); 78 | 79 | output->connect_signal("wm-actions-above-changed", &on_view_keep_above); 80 | 81 | output->connect_signal("output-configuration-changed", 82 | &output_configuration_changed); 83 | 84 | output->connect_signal("view-minimize-request", &output_view_minimized); 85 | 86 | output->connect_signal("view-tile-request", &output_view_maximized); 87 | 88 | output->connect_signal("view-move-request", &output_view_moving); 89 | 90 | output->connect_signal("view-resize-request", &output_view_resizing); 91 | 92 | output->connect_signal("view-change-viewport", &view_workspaces_changed); 93 | 94 | output->connect_signal("workspace-changed", &output_workspace_changed); 95 | 96 | output->connect_signal("view-layer-attached", &role_changed); 97 | 98 | output->connect_signal("view-layer-detached", &role_changed); 99 | 100 | output->connect_signal("view-focused", &output_view_focus_changed); 101 | 102 | output->connect_signal("view-fullscreen-request", 103 | &view_fullscreen_changed); 104 | #ifdef DBUS_PLUGIN_DEBUG 105 | LOG(wf::log::LOG_LEVEL_DEBUG, "output connected"); 106 | #endif 107 | connected_wf_outputs.insert(output); 108 | } 109 | 110 | for (wayfire_view view : core.get_all_views()) 111 | { 112 | view->connect_signal("app-id-changed", &view_app_id_changed); 113 | 114 | view->connect_signal("title-changed", &view_title_changed); 115 | 116 | view->connect_signal("geometry-changed", &view_geometry_changed); 117 | 118 | view->connect_signal("unmapped", &view_closed); 119 | 120 | view->connect_signal("tiled", &view_tiled); 121 | 122 | view->connect_signal("ping-timeout", &view_timeout); 123 | 124 | // view->connect_signal("subsurface-added", &subsurface_added); 125 | } 126 | 127 | /****************** Connect core signals ***********************/ 128 | 129 | core.connect_signal("view-hints-changed", &view_hints_changed); 130 | 131 | core.connect_signal("view-focus-request", &view_focus_request); 132 | 133 | core.connect_signal("view-pre-moved-to-output", 134 | &view_output_move_requested); 135 | 136 | core.connect_signal("view-moved-to-output", &view_output_moved); 137 | 138 | core.connect_signal("pointer_button", &pointer_button_signal); 139 | 140 | core.connect_signal("tablet_button", &tablet_button_signal); 141 | 142 | core.output_layout->connect_signal("output-added", 143 | &output_layout_output_added); 144 | 145 | core.output_layout->connect_signal("output-removed", 146 | &output_layout_output_removed); 147 | 148 | g_signal_connect(settings, "changed", G_CALLBACK(settings_changed), NULL); 149 | geometry_signal = g_settings_get_boolean(settings, "geometry-signal"); 150 | 151 | acquire_bus(); 152 | gchar *startup_notify_cmd = NULL; 153 | startup_notify_cmd = g_settings_get_string(settings, "startup-notify"); 154 | if (g_strcmp0(startup_notify_cmd, "") != 0) { 155 | LOG(wf::log::LOG_LEVEL_DEBUG, "Running startup up notify:", 156 | startup_notify_cmd); 157 | core.run(startup_notify_cmd); 158 | } 159 | g_free(startup_notify_cmd); 160 | } 161 | 162 | ~dbus_interface_t() 163 | { 164 | /* 165 | * There are probably a lot of things missing here. 166 | * 167 | * For my use-case it should never be unloaded. 168 | * Feel free to open PR for clean unloading. 169 | */ 170 | #ifdef DBUS_PLUGIN_DEBUG 171 | LOG(wf::log::LOG_LEVEL_DEBUG, "Unloading DBus Plugin"); 172 | #endif 173 | 174 | g_bus_unown_name(owner_id); 175 | g_dbus_node_info_unref(introspection_data); 176 | g_object_unref(settings); 177 | dbus_scale_filter::unload(); 178 | } 179 | 180 | /******************************View Related Slots***************************/ 181 | /*** 182 | * A pointer button is interacted with 183 | ***/ 184 | wf::signal_connection_t pointer_button_signal{[=] (wf::signal_data_t* data) 185 | { 186 | #ifdef DBUS_PLUGIN_DEBUG 187 | LOG(wf::log::LOG_LEVEL_DEBUG, "pointer_button_signal"); 188 | #endif 189 | wf::pointf_t cursor_position; 190 | GVariant* signal_data; 191 | wf::input_event_signal<wlr_event_pointer_button>* wf_ev; 192 | wlr_event_pointer_button* wlr_signal; 193 | wlr_button_state button_state; 194 | bool button_released; 195 | uint32_t button; 196 | 197 | cursor_position = core.get_cursor_position(); 198 | wf_ev = 199 | static_cast<wf::input_event_signal<wlr_event_pointer_button>*> (data); 200 | wlr_signal = static_cast<wlr_event_pointer_button*> (wf_ev->event); 201 | button_state = wlr_signal->state; 202 | button = wlr_signal->button; 203 | button_released = (button_state == WLR_BUTTON_RELEASED); 204 | 205 | if (find_view_under_action && button_released) { 206 | GVariant* _signal_data; 207 | wayfire_view view; 208 | view = core.get_view_at(cursor_position); 209 | _signal_data = g_variant_new("(u)", view ? view->get_id() : 0); 210 | g_variant_ref(_signal_data); 211 | bus_emit_signal("view_pressed", _signal_data); 212 | } 213 | 214 | signal_data = g_variant_new("(ddub)", cursor_position.x, cursor_position.y, 215 | button, button_released); 216 | g_variant_ref(signal_data); 217 | bus_emit_signal("pointer_clicked", signal_data); 218 | } 219 | }; 220 | 221 | /*** 222 | * A tablet button is interacted with 223 | * TODO: do more for touch events 224 | ***/ 225 | wf::signal_connection_t tablet_button_signal{[=] (wf::signal_data_t* data) 226 | { 227 | #ifdef DBUS_PLUGIN_DEBUG 228 | LOG(wf::log::LOG_LEVEL_DEBUG, "tablet_button_signal"); 229 | #endif 230 | bus_emit_signal("tablet_touched", nullptr); 231 | } 232 | }; 233 | 234 | /*** 235 | * A new view is added to an output. 236 | ***/ 237 | wf::signal_connection_t output_view_added{[=] (wf::signal_data_t* data) 238 | { 239 | #ifdef DBUS_PLUGIN_DEBUG 240 | LOG(wf::log::LOG_LEVEL_DEBUG, "output_view_added"); 241 | #endif 242 | 243 | GVariant* signal_data; 244 | wayfire_view view; 245 | 246 | view = get_signaled_view(data); 247 | if (!view) { 248 | #ifdef DBUS_PLUGIN_DEBUG 249 | LOG(wf::log::LOG_LEVEL_DEBUG, "output_view_added no view"); 250 | #endif 251 | 252 | return; 253 | } 254 | 255 | signal_data = g_variant_new("(u)", view->get_id()); 256 | g_variant_ref(signal_data); 257 | bus_emit_signal("view_added", signal_data); 258 | 259 | view->connect_signal("app-id-changed", &view_app_id_changed); 260 | view->connect_signal("title-changed", &view_title_changed); 261 | view->connect_signal("geometry-changed", &view_geometry_changed); 262 | view->connect_signal("unmapped", &view_closed); 263 | view->connect_signal("tiled", &view_tiled); 264 | view->connect_signal("ping-timeout", &view_timeout); 265 | // view->connect_signal("subsurface-added", &subsurface_added); 266 | } 267 | }; 268 | 269 | // wf::signal_connection_t subsurface_added{[=](wf::signal_data_t *data) { 270 | // LOGE("subsurface_added signal"); 271 | // }}; 272 | 273 | /*** 274 | * The View has received ping timeout. 275 | ***/ 276 | wf::signal_connection_t view_timeout{[=] (wf::signal_data_t* data) 277 | { 278 | GVariant* signal_data; 279 | wayfire_view view; 280 | view = get_signaled_view(data); 281 | 282 | if (!view) { 283 | LOGE("view_timeout no view"); 284 | 285 | return; 286 | } 287 | 288 | LOGE("view_timeout ", view->get_id()); 289 | 290 | signal_data = g_variant_new("(u)", view->get_id()); 291 | g_variant_ref(signal_data); 292 | bus_emit_signal("view_timeout", signal_data); 293 | } 294 | }; 295 | 296 | /*** 297 | * The view has closed. 298 | ***/ 299 | wf::signal_connection_t view_closed{[=] (wf::signal_data_t* data) 300 | { 301 | #ifdef DBUS_PLUGIN_DEBUG 302 | LOG(wf::log::LOG_LEVEL_DEBUG, "view_closed"); 303 | #endif 304 | 305 | GVariant* signal_data; 306 | wayfire_view view; 307 | 308 | view = get_signaled_view(data); 309 | 310 | if (!view) { 311 | #ifdef DBUS_PLUGIN_DEBUG 312 | LOG(wf::log::LOG_LEVEL_DEBUG, "view_closed no view"); 313 | #endif 314 | 315 | return; 316 | } 317 | 318 | signal_data = g_variant_new("(u)", view->get_id()); 319 | g_variant_ref(signal_data); 320 | bus_emit_signal("view_closed", signal_data); 321 | } 322 | }; 323 | 324 | /*** 325 | * The view's app_id has changed. 326 | ***/ 327 | wf::signal_connection_t view_app_id_changed{[=] (wf::signal_data_t* data) 328 | { 329 | #ifdef DBUS_PLUGIN_DEBUG 330 | LOG(wf::log::LOG_LEVEL_DEBUG, "view_app_id_changed"); 331 | #endif 332 | 333 | GVariant* signal_data; 334 | wayfire_view view; 335 | 336 | view = get_signaled_view(data); 337 | if (!view) { 338 | #ifdef DBUS_PLUGIN_DEBUG 339 | 340 | LOG(wf::log::LOG_LEVEL_DEBUG, "view_app_id_changed no view"); 341 | #endif 342 | 343 | return; 344 | } 345 | 346 | signal_data = 347 | g_variant_new("(us)", view->get_id(), view->get_app_id().c_str()); 348 | g_variant_ref(signal_data); 349 | bus_emit_signal("view_app_id_changed", signal_data); 350 | } 351 | }; 352 | 353 | /*** 354 | * The view's title has changed. 355 | ***/ 356 | wf::signal_connection_t view_title_changed{[=] (wf::signal_data_t* data) 357 | { 358 | #ifdef DBUS_PLUGIN_DEBUG 359 | LOG(wf::log::LOG_LEVEL_DEBUG, "view_title_changed"); 360 | #endif 361 | 362 | GVariant* signal_data; 363 | wayfire_view view; 364 | 365 | view = get_signaled_view(data); 366 | if (!check_view_toplevel) { 367 | return; 368 | } 369 | 370 | signal_data = 371 | g_variant_new("(us)", view->get_id(), view->get_title().c_str()); 372 | g_variant_ref(signal_data); 373 | bus_emit_signal("view_title_changed", signal_data); 374 | } 375 | }; 376 | 377 | /*** 378 | * The view's fullscreen status has changed. 379 | ***/ 380 | wf::signal_connection_t view_fullscreen_changed{[=] (wf::signal_data_t* data) 381 | { 382 | #ifdef DBUS_PLUGIN_DEBUG 383 | LOG(wf::log::LOG_LEVEL_DEBUG, "view_fullscreened"); 384 | #endif 385 | 386 | wf::view_fullscreen_signal* signal; 387 | GVariant* signal_data; 388 | wayfire_view view; 389 | 390 | signal = static_cast<wf::view_fullscreen_signal*> (data); 391 | view = signal->view; 392 | signal_data = g_variant_new("(ub)", view->get_id(), signal->state); 393 | g_variant_ref(signal_data); 394 | bus_emit_signal("view_fullscreen_changed", signal_data); 395 | } 396 | }; 397 | 398 | /*** 399 | * The view's geometry has changed. 400 | ***/ 401 | wf::signal_connection_t view_geometry_changed{[=] (wf::signal_data_t* data) 402 | { 403 | if (!geometry_signal) { 404 | return; 405 | } 406 | 407 | #ifdef DBUS_PLUGIN_DEBUG 408 | 409 | LOG(wf::log::LOG_LEVEL_DEBUG, "view_geometry_changed"); 410 | #endif 411 | 412 | GVariant* signal_data; 413 | wayfire_view view; 414 | wf::geometry_t geometry; 415 | 416 | view = get_signaled_view(data); 417 | geometry = view->get_output_geometry(); 418 | signal_data = g_variant_new("(uiiii)", view->get_id(), geometry.x, 419 | geometry.y, geometry.width, geometry.height); 420 | g_variant_ref(signal_data); 421 | bus_emit_signal("view_geometry_changed", signal_data); 422 | } 423 | }; 424 | 425 | /*** 426 | * The view's tiling status has changed. 427 | ***/ 428 | wf::signal_connection_t view_tiled{[=] (wf::signal_data_t* data) 429 | { 430 | #ifdef DBUS_PLUGIN_DEBUG 431 | LOG(wf::log::LOG_LEVEL_DEBUG, "view_tiled"); 432 | #endif 433 | 434 | GVariant* signal_data; 435 | wf::view_tiled_signal* signal; 436 | wayfire_view view; 437 | 438 | signal = static_cast<wf::view_tiled_signal*> (data); 439 | view = signal->view; 440 | 441 | if (!check_view_toplevel) { 442 | return; 443 | } 444 | 445 | signal_data = g_variant_new("(uu)", view->get_id(), signal->new_edges); 446 | g_variant_ref(signal_data); 447 | bus_emit_signal("view_tiling_changed", signal_data); 448 | } 449 | }; 450 | 451 | /*** 452 | * The view's output has changed. 453 | ***/ 454 | wf::signal_connection_t view_output_moved{[=] (wf::signal_data_t* data) 455 | { 456 | #ifdef DBUS_PLUGIN_DEBUG 457 | LOG(wf::log::LOG_LEVEL_DEBUG, "view_output_moved"); 458 | #endif 459 | 460 | wf::view_moved_to_output_signal* signal; 461 | GVariant* signal_data; 462 | wayfire_view view; 463 | wf::output_t* old_output; 464 | wf::output_t* new_output; 465 | 466 | signal = static_cast<wf::view_moved_to_output_signal*> (data); 467 | view = signal->view; 468 | 469 | if (!check_view_toplevel) { 470 | return; 471 | } 472 | 473 | old_output = signal->old_output; 474 | new_output = signal->new_output; 475 | 476 | signal_data = g_variant_new("(uuu)", view->get_id(), old_output->get_id(), 477 | new_output->get_id()); 478 | g_variant_ref(signal_data); 479 | bus_emit_signal("view_output_moved", signal_data); 480 | } 481 | }; 482 | 483 | /*** 484 | * The view's output is about to change. 485 | ***/ 486 | wf::signal_connection_t view_output_move_requested{ 487 | [=] (wf::signal_data_t* data) 488 | { 489 | #ifdef DBUS_PLUGIN_DEBUG 490 | LOG(wf::log::LOG_LEVEL_DEBUG, "view_output_move_requested"); 491 | #endif 492 | 493 | GVariant* signal_data; 494 | wf::view_pre_moved_to_output_signal* signal; 495 | wf::output_t* old_output; 496 | wf::output_t* new_output; 497 | wayfire_view view; 498 | 499 | signal = static_cast<wf::view_pre_moved_to_output_signal*> (data); 500 | view = signal->view; 501 | 502 | if (view) { 503 | old_output = signal->old_output; 504 | new_output = signal->new_output; 505 | signal_data = 506 | g_variant_new("(uuu)", view->get_id(), old_output->get_id(), 507 | new_output->get_id()); 508 | g_variant_ref(signal_data); 509 | bus_emit_signal("view_output_move_requested", signal_data); 510 | } 511 | } 512 | }; 513 | 514 | /*** 515 | * The view's role has changed. 516 | ***/ 517 | wf::signal_connection_t role_changed{[=] (wf::signal_data_t* data) 518 | { 519 | #ifdef DBUS_PLUGIN_DEBUG 520 | LOG(wf::log::LOG_LEVEL_DEBUG, "role_changed"); 521 | #endif 522 | 523 | GVariant* signal_data; 524 | wayfire_view view; 525 | 526 | view = get_signaled_view(data); 527 | 528 | if (!view) { 529 | #ifdef DBUS_PLUGIN_DEBUG 530 | LOG(wf::log::LOG_LEVEL_DEBUG, "role_changed no view"); 531 | #endif 532 | 533 | return; 534 | } 535 | 536 | uint role = 0; 537 | 538 | if (view->role == wf::VIEW_ROLE_TOPLEVEL) { 539 | role = 1; 540 | } 541 | else 542 | if (view->role == wf::VIEW_ROLE_DESKTOP_ENVIRONMENT) 543 | { 544 | role = 2; 545 | } 546 | else 547 | if (view->role == wf::VIEW_ROLE_UNMANAGED) 548 | { 549 | role = 3; 550 | } 551 | 552 | signal_data = g_variant_new("(uu)", view->get_id(), role); 553 | g_variant_ref(signal_data); 554 | bus_emit_signal("view_role_changed", signal_data); 555 | } 556 | }; 557 | 558 | /*** 559 | * The view's workspaces have changed. 560 | ***/ 561 | wf::signal_connection_t view_workspaces_changed{[=] (wf::signal_data_t* data) 562 | { 563 | #ifdef DBUS_PLUGIN_DEBUG 564 | LOG(wf::log::LOG_LEVEL_DEBUG, "view_workspaces_changed"); 565 | #endif 566 | 567 | GVariant* signal_data; 568 | view_change_viewport_signal* signal; 569 | wayfire_view view; 570 | 571 | signal = static_cast<view_change_viewport_signal*> (data); 572 | view = signal->view; 573 | 574 | if (!check_view_toplevel) { 575 | return; 576 | } 577 | 578 | signal_data = g_variant_new("(u)", view->get_id()); 579 | 580 | g_variant_ref(signal_data); 581 | bus_emit_signal("view_workspaces_changed", signal_data); 582 | } 583 | }; 584 | 585 | /*** 586 | * The view's maximized status has changed. 587 | ***/ 588 | wf::signal_connection_t output_view_maximized{[=] (wf::signal_data_t* data) 589 | { 590 | #ifdef DBUS_PLUGIN_DEBUG 591 | LOG(wf::log::LOG_LEVEL_DEBUG, "output_view_maximized"); 592 | #endif 593 | 594 | wf::view_tiled_signal* signal; 595 | GVariant* signal_data; 596 | wayfire_view view; 597 | bool maximized; 598 | 599 | signal = static_cast<wf::view_tiled_signal*> (data); 600 | view = signal->view; 601 | 602 | if (!check_view_toplevel) { 603 | return; 604 | } 605 | 606 | maximized = (signal->new_edges == wf::TILED_EDGES_ALL); 607 | signal_data = g_variant_new("(ub)", view->get_id(), maximized); 608 | g_variant_ref(signal_data); 609 | bus_emit_signal("view_maximized_changed", signal_data); 610 | } 611 | }; 612 | 613 | /*** 614 | * The view's minimized status has changed. 615 | ***/ 616 | wf::signal_connection_t output_view_minimized{[=] (wf::signal_data_t* data) 617 | { 618 | #ifdef DBUS_PLUGIN_DEBUG 619 | LOG(wf::log::LOG_LEVEL_DEBUG, "output_view_minimized"); 620 | #endif 621 | 622 | GVariant* signal_data; 623 | wf::view_minimize_request_signal* signal; 624 | wayfire_view view; 625 | bool minimized; 626 | 627 | signal = static_cast<wf::view_minimize_request_signal*> (data); 628 | view = signal->view; 629 | 630 | if (!check_view_toplevel) { 631 | return; 632 | } 633 | 634 | minimized = signal->state; 635 | signal_data = g_variant_new("(ub)", view->get_id(), minimized); 636 | g_variant_ref(signal_data); 637 | bus_emit_signal("view_minimized_changed", signal_data); 638 | } 639 | }; 640 | 641 | /*** 642 | * The view's focus has changed. 643 | ***/ 644 | wf::signal_connection_t output_view_focus_changed{ 645 | [=] (wf::signal_data_t* data) 646 | { 647 | GVariant* signal_data; 648 | wf::focus_view_signal* signal; 649 | wayfire_view view; 650 | uint view_id; 651 | 652 | signal = static_cast<wf::focus_view_signal*> (data); 653 | view = signal->view; 654 | 655 | if (!check_view_toplevel) { 656 | return; 657 | } 658 | 659 | view_id = view->get_id(); 660 | 661 | if (view_id == focused_view_id) { 662 | #ifdef DBUS_PLUGIN_DEBUG 663 | LOG(wf::log::LOG_LEVEL_DEBUG, 664 | "output_view_focus_changed old focus view"); 665 | #endif 666 | 667 | return; 668 | } 669 | 670 | if (view->role != wf::VIEW_ROLE_TOPLEVEL) { 671 | #ifdef DBUS_PLUGIN_DEBUG 672 | LOG(wf::log::LOG_LEVEL_DEBUG, 673 | "output_view_focus_changed not a toplevel "); 674 | #endif 675 | 676 | return; 677 | } 678 | 679 | if (!view->activated) { 680 | return; 681 | } 682 | 683 | if (view->has_data("view-demands-attention")) { 684 | view->erase_data("view-demands-attention"); 685 | } 686 | 687 | focused_view_id = view_id; 688 | signal_data = g_variant_new("(u)", view_id); 689 | g_variant_ref(signal_data); 690 | bus_emit_signal("view_focus_changed", signal_data); 691 | } 692 | }; 693 | 694 | /*** 695 | * The view hints demands focus 696 | * Examples: 697 | * 1) applications that get dbus activated 698 | * 2) Multiplayer games if game is found. 699 | * (source engine does this) 700 | ***/ 701 | wf::signal_connection_t view_focus_request{[=] (wf::signal_data_t* data) 702 | { 703 | #ifdef DBUS_PLUGIN_DEBUG 704 | LOG(wf::log::LOG_LEVEL_DEBUG, "view_focus_request_signal"); 705 | #endif 706 | bool reconfigure = true; 707 | wf::view_focus_request_signal* signal; 708 | wayfire_view view; 709 | wf::output_t* active_output; 710 | wf::output_t* view_output; 711 | 712 | signal = static_cast<wf::view_focus_request_signal*> (data); 713 | if (signal->carried_out) { 714 | return; 715 | } 716 | 717 | if (!signal->self_request) { 718 | return; 719 | } 720 | 721 | view = signal->view; 722 | 723 | if (!check_view_toplevel) { 724 | return; 725 | } 726 | 727 | active_output = core.get_active_output(); 728 | view_output = view->get_output(); 729 | // it is possible to also change the view''s 730 | // output e.g for single window applications 731 | // but other applications call sef_request_focus 732 | // for other reasons and this would change 733 | // it's output where it is completely undesired 734 | // if (view_output) 735 | // { 736 | // if (view_output != active_output) 737 | // { 738 | // } 739 | // } 740 | 741 | signal->carried_out = true; 742 | view->set_activated(true); 743 | view->focus_request(); 744 | } 745 | }; 746 | 747 | /*** 748 | * The view hints have changed 749 | * The currently ownly interesting hint 750 | * is view-demands-attention 751 | ***/ 752 | wf::signal_connection_t view_hints_changed{[=] (wf::signal_data_t* data) 753 | { 754 | wf::view_hints_changed_signal* signal; 755 | GVariant* signal_data; 756 | bool view_wants_attention = false; 757 | wayfire_view view; 758 | 759 | signal = static_cast<wf::view_hints_changed_signal*> (data); 760 | view = signal->view; 761 | 762 | if (!check_view_toplevel) { 763 | #ifdef DBUS_PLUGIN_DEBUG 764 | 765 | LOG(wf::log::LOG_LEVEL_DEBUG, "view_hints_changed no view"); 766 | #endif 767 | 768 | return; 769 | } 770 | 771 | #ifdef DBUS_PLUGIN_DEBUG 772 | 773 | LOG(wf::log::LOG_LEVEL_DEBUG, "view_hints_changed", 774 | view->has_data("view-demands-attention")); 775 | #endif 776 | if (view->has_data("view-demands-attention")) { 777 | view_wants_attention = true; 778 | } 779 | 780 | signal_data = g_variant_new("(ub)", view->get_id(), view_wants_attention); 781 | g_variant_ref(signal_data); 782 | bus_emit_signal("view_attention_changed", signal_data); 783 | } 784 | }; 785 | 786 | /*** 787 | * The view may or may not be moving now. 788 | * The status of that has somehow changed. 789 | * https://github.com/WayfireWM/wayfire/issues/639 790 | ***/ 791 | wf::signal_connection_t output_view_moving{[=] (wf::signal_data_t* data) 792 | { 793 | #ifdef DBUS_PLUGIN_DEBUG 794 | LOG(wf::log::LOG_LEVEL_DEBUG, "output_view_moving"); 795 | #endif 796 | 797 | GVariant* signal_data; 798 | wayfire_view view; 799 | 800 | view = get_signaled_view(data); 801 | 802 | if (!check_view_toplevel) { 803 | return; 804 | } 805 | 806 | signal_data = g_variant_new("(u)", view->get_id()); 807 | g_variant_ref(signal_data); 808 | bus_emit_signal("view_moving_changed", signal_data); 809 | } 810 | }; 811 | 812 | /*** 813 | * The view may or may not be resizing now. 814 | * The status of that has somehow changed. 815 | * https://github.com/WayfireWM/wayfire/issues/639 816 | ***/ 817 | wf::signal_connection_t output_view_resizing{[=] (wf::signal_data_t* data) 818 | { 819 | #ifdef DBUS_PLUGIN_DEBUG 820 | LOG(wf::log::LOG_LEVEL_DEBUG, "output_view_resizing"); 821 | #endif 822 | 823 | GVariant* signal_data; 824 | wayfire_view view; 825 | 826 | view = get_signaled_view(data); 827 | 828 | if (!check_view_toplevel) { 829 | return; 830 | } 831 | 832 | signal_data = g_variant_new("(u)", view->get_id()); 833 | g_variant_ref(signal_data); 834 | bus_emit_signal("view_resizing_changed", signal_data); 835 | } 836 | }; 837 | 838 | /*** 839 | * The wm-actions plugin changed the above_layer 840 | * state of a view. 841 | ***/ 842 | wf::signal_connection_t on_view_keep_above{[=] (wf::signal_data_t* data) 843 | { 844 | GVariant* signal_data; 845 | wayfire_view view; 846 | 847 | view = wf::get_signaled_view(data); 848 | 849 | if (!check_view_toplevel) { 850 | return; 851 | } 852 | 853 | signal_data = g_variant_new("(ub)", view->get_id(), 854 | view->has_data("wm-actions-above")); 855 | g_variant_ref(signal_data); 856 | bus_emit_signal("view_keep_above_changed", signal_data); 857 | } 858 | }; 859 | 860 | /*** 861 | * The decoration of a view has changed 862 | ***/ 863 | wf::signal_connection_t output_view_decoration_changed{ 864 | [=] (wf::signal_data_t* data) 865 | { 866 | } 867 | }; 868 | 869 | /*** 870 | * No usecase has been found for these 3 871 | ***/ 872 | wf::signal_connection_t output_detach_view{[=] (wf::signal_data_t* data) 873 | { 874 | } 875 | }; 876 | wf::signal_connection_t output_view_disappeared{ 877 | [=] (wf::signal_data_t* data) 878 | { 879 | } 880 | }; 881 | wf::signal_connection_t output_view_attached{[=] (wf::signal_data_t* data) 882 | { 883 | } 884 | }; 885 | 886 | /******************************Output Related 887 | * Slots***************************/ 888 | 889 | /*** 890 | * If the output configuration is changed somehow, 891 | * scaling / resolution etc changes, this is emitted 892 | ***/ 893 | wf::signal_connection_t output_configuration_changed{ 894 | [=] (wf::signal_data_t* data) 895 | { 896 | #ifdef DBUS_PLUGIN_DEBUG 897 | LOG(wf::log::LOG_LEVEL_DEBUG, "output_configuration_changed"); 898 | #endif 899 | 900 | bus_emit_signal("output_configuration_changed", nullptr); 901 | } 902 | }; 903 | 904 | /*** 905 | * The workspace of an output changed 906 | ***/ 907 | wf::signal_connection_t output_workspace_changed{ 908 | [=] (wf::signal_data_t* data) 909 | { 910 | #ifdef DBUS_PLUGIN_DEBUG 911 | LOG(wf::log::LOG_LEVEL_DEBUG, "output_workspace_changed"); 912 | #endif 913 | 914 | wf::workspace_changed_signal* signal; 915 | GVariant* signal_data; 916 | wf::output_t* output; 917 | int newHorizontalWorkspace; 918 | int newVerticalWorkspace; 919 | 920 | signal = static_cast<wf::workspace_changed_signal*> (data); 921 | newHorizontalWorkspace = signal->new_viewport.x; 922 | newVerticalWorkspace = signal->new_viewport.y; 923 | output = signal->output; 924 | signal_data = 925 | g_variant_new("(uii)", output->get_id(), newHorizontalWorkspace, 926 | newVerticalWorkspace); 927 | 928 | g_variant_ref(signal_data); 929 | bus_emit_signal("output_workspace_changed", signal_data); 930 | } 931 | }; 932 | 933 | /*** 934 | * A new output has been added 935 | ***/ 936 | wf::signal_connection_t output_layout_output_added{ 937 | [=] (wf::signal_data_t* data) 938 | { 939 | #ifdef DBUS_PLUGIN_DEBUG 940 | LOG(wf::log::LOG_LEVEL_DEBUG, "output_layout_output_added"); 941 | #endif 942 | wf::output_t* output; 943 | GVariant* signal_data; 944 | 945 | output = get_signaled_output(data); 946 | auto search = connected_wf_outputs.find(output); 947 | 948 | if (search != connected_wf_outputs.end()) { 949 | return; 950 | } 951 | 952 | grab_interfaces[output] = 953 | std::make_unique<wf::plugin_grab_interface_t> (output); 954 | grab_interfaces[output]->name = "dbus"; 955 | grab_interfaces[output]->capabilities = wf::CAPABILITY_GRAB_INPUT; 956 | 957 | output->connect_signal("wm-actions-above-changed", &on_view_keep_above); 958 | 959 | output->connect_signal("view-fullscreen-request", 960 | &view_fullscreen_changed); 961 | 962 | output->connect_signal("view-mapped", &output_view_added); 963 | 964 | output->connect_signal("output-configuration-changed", 965 | &output_configuration_changed); 966 | 967 | output->connect_signal("view-minimize-request", &output_view_minimized); 968 | 969 | output->connect_signal("view-tile-request", &output_view_maximized); 970 | 971 | output->connect_signal("view-move-request", &output_view_moving); 972 | 973 | output->connect_signal("view-change-viewport", 974 | &view_workspaces_changed); 975 | 976 | output->connect_signal("workspace-changed", &output_workspace_changed); 977 | 978 | output->connect_signal("view-resize-request", &output_view_resizing); 979 | 980 | output->connect_signal("view-focused", &output_view_focus_changed); 981 | 982 | output->connect_signal("view-layer-attached", &role_changed); 983 | 984 | output->connect_signal("view-layer-detached", &role_changed); 985 | 986 | wf_outputs = core.output_layout->get_outputs(); 987 | connected_wf_outputs.insert(output); 988 | 989 | signal_data = g_variant_new("(u)", output->get_id()); 990 | g_variant_ref(signal_data); 991 | bus_emit_signal("output_added", signal_data); 992 | } 993 | }; 994 | 995 | /*** 996 | * An output has been removed 997 | ***/ 998 | wf::signal_connection_t output_layout_output_removed{ 999 | [=] (wf::signal_data_t* data) 1000 | { 1001 | #ifdef DBUS_PLUGIN_DEBUG 1002 | LOG(wf::log::LOG_LEVEL_DEBUG, "output_layout_output_removed"); 1003 | #endif 1004 | GVariant* signal_data; 1005 | wf::output_t* output; 1006 | 1007 | output = get_signaled_output(data); 1008 | auto search = connected_wf_outputs.find(output); 1009 | 1010 | if (search != connected_wf_outputs.end()) { 1011 | wf_outputs = core.output_layout->get_outputs(); 1012 | connected_wf_outputs.erase(output); 1013 | 1014 | signal_data = g_variant_new("(u)", output->get_id()); 1015 | g_variant_ref(signal_data); 1016 | bus_emit_signal("output_removed", signal_data); 1017 | } 1018 | 1019 | grab_interfaces.erase(output); 1020 | 1021 | // maybe use pre-removed instead? 1022 | } 1023 | }; 1024 | }; 1025 | 1026 | DECLARE_WAYFIRE_PLUGIN((wf::singleton_plugin_t<dbus_interface_t, false>)); 1027 | // bool = unloadable 1028 | -------------------------------------------------------------------------------- /uncrustify.ini: -------------------------------------------------------------------------------- 1 | # Uncrustify_d-0.71.0-21-d4da2b0f 2 | 3 | # 4 | # General options 5 | # 6 | 7 | # The type of line endings. 8 | # 9 | # Default: auto 10 | newlines = auto # lf/crlf/cr/auto 11 | 12 | # The original size of tabs in the input. 13 | # 14 | # Default: 8 15 | input_tab_size = 4 # unsigned number 16 | 17 | # The size of tabs in the output (only used if align_with_tabs=true). 18 | # 19 | # Default: 8 20 | output_tab_size = 3 # unsigned number 21 | 22 | # The ASCII value of the string escape char, usually 92 (\) or (Pawn) 94 (^). 23 | # 24 | # Default: 92 25 | string_escape_char = 92 # unsigned number 26 | 27 | # Alternate string escape char (usually only used for Pawn). 28 | # Only works right before the quote char. 29 | string_escape_char2 = 0 # unsigned number 30 | 31 | # Replace tab characters found in string literals with the escape sequence \t 32 | # instead. 33 | string_replace_tab_chars = true # true/false 34 | 35 | # Allow interpreting '>=' and '>>=' as part of a template in code like 36 | # 'void f(list<list<B>>=val);'. If true, 'assert(x<0 && y>=3)' will be broken. 37 | # Improvements to template detection may make this option obsolete. 38 | tok_split_gte = false # true/false 39 | 40 | # Disable formatting of NL_CONT ('\\n') ended lines (e.g. multiline macros) 41 | disable_processing_nl_cont = false # true/false 42 | 43 | # Specify the marker used in comments to disable processing of part of the 44 | # file. 45 | # The comment should be used alone in one line. 46 | # 47 | # Default: *INDENT-OFF* 48 | disable_processing_cmt = " *INDENT-OFF*" # string 49 | 50 | # Specify the marker used in comments to (re)enable processing in a file. 51 | # The comment should be used alone in one line. 52 | # 53 | # Default: *INDENT-ON* 54 | enable_processing_cmt = " *INDENT-ON*" # string 55 | 56 | # Enable parsing of digraphs. 57 | enable_digraphs = false # true/false 58 | 59 | # Add or remove the UTF-8 BOM (recommend 'remove'). 60 | utf8_bom = ignore # ignore/add/remove/force 61 | 62 | # If the file contains bytes with values between 128 and 255, but is not 63 | # UTF-8, then output as UTF-8. 64 | utf8_byte = false # true/false 65 | 66 | # Force the output encoding to UTF-8. 67 | utf8_force = false # true/false 68 | 69 | # Add or remove space between 'do' and '{'. 70 | sp_do_brace_open = add # ignore/add/remove/force 71 | 72 | # Add or remove space between '}' and 'while'. 73 | sp_brace_close_while = add # ignore/add/remove/force 74 | 75 | # Add or remove space between 'while' and '('. 76 | sp_while_paren_open = add # ignore/add/remove/force 77 | 78 | # 79 | # Spacing options 80 | # 81 | 82 | # Add or remove space around non-assignment symbolic operators ('+', '/', '%', 83 | # '<<', and so forth). 84 | sp_arith = force # ignore/add/remove/force 85 | 86 | # Add or remove space around assignment operator '=', '+=', etc. 87 | sp_assign = force # ignore/add/remove/force 88 | 89 | # Add or remove space around '=' in C++11 lambda capture specifications. 90 | # 91 | # Overrides sp_assign. 92 | sp_cpp_lambda_assign = remove # ignore/add/remove/force 93 | 94 | # Add or remove space after the capture specification of a C++11 lambda when 95 | # an argument list is present, as in '[] <here> (int x){ ... }'. 96 | sp_cpp_lambda_square_paren = force # ignore/add/remove/force 97 | 98 | # Add or remove space after the capture specification of a C++11 lambda with 99 | # no argument list is present, as in '[] <here> { ... }'. 100 | sp_cpp_lambda_square_brace = force # ignore/add/remove/force 101 | 102 | # Add or remove space after the argument list of a C++11 lambda, as in 103 | # '[](int x) <here> { ... }'. 104 | sp_cpp_lambda_paren_brace = force # ignore/add/remove/force 105 | 106 | # Add or remove space in 'NS_ENUM ('. 107 | sp_enum_paren = ignore # ignore/add/remove/force 108 | 109 | # Add or remove space around assignment '=' in enum. 110 | sp_enum_assign = add # ignore/add/remove/force 111 | 112 | # Add or remove space around assignment ':' in enum. 113 | sp_enum_colon = add # ignore/add/remove/force 114 | 115 | # Add or remove space around boolean operators '&&' and '||'. 116 | sp_bool = add # ignore/add/remove/force 117 | 118 | # Add or remove space around compare operator '<', '>', '==', etc. 119 | sp_compare = force # ignore/add/remove/force 120 | 121 | # Add or remove space inside '(' and ')'. 122 | sp_inside_paren = remove # ignore/add/remove/force 123 | 124 | # Add or remove space between nested parentheses, i.e. '((' vs. ') )'. 125 | sp_paren_paren = remove # ignore/add/remove/force 126 | 127 | # Add or remove space between back-to-back parentheses, i.e. ')(' vs. ') ('. 128 | sp_cparen_oparen = remove # ignore/add/remove/force 129 | 130 | # Add or remove space between ')' and '{'. 131 | sp_paren_brace = add # ignore/add/remove/force 132 | 133 | # Add or remove space between nested braces, i.e. '{{' vs '{ {'. 134 | sp_brace_brace = remove # ignore/add/remove/force 135 | 136 | # Add or remove space before pointer star '*'. 137 | sp_before_ptr_star = remove # ignore/add/remove/force 138 | 139 | # Add or remove space between pointer stars '*'. 140 | sp_between_ptr_star = remove # ignore/add/remove/force 141 | 142 | # Add or remove space after pointer star '*', if followed by a word. 143 | # 144 | # Overrides sp_type_func. 145 | sp_after_ptr_star = add # ignore/add/remove/force 146 | 147 | # Add or remove space before pointer star '*' that isn't followed by a 148 | # variable name. If set to ignore, sp_before_ptr_star is used instead. 149 | sp_before_unnamed_ptr_star = remove # ignore/add/remove/force 150 | 151 | # Add or remove space before a pointer star '*', if followed by a function 152 | # prototype or function definition. 153 | sp_before_ptr_star_func = remove # ignore/add/remove/force 154 | 155 | # Add or remove space before a reference sign '&'. 156 | sp_before_byref = remove # ignore/add/remove/force 157 | 158 | # Add or remove space after reference sign '&', if followed by a word. 159 | # 160 | # Overrides sp_type_func. 161 | sp_after_byref = add # ignore/add/remove/force 162 | 163 | # Add or remove space before a reference sign '&', if followed by a function 164 | # prototype or function definition. 165 | sp_before_byref_func = remove # ignore/add/remove/force 166 | 167 | # Add or remove space between 'decltype(...)' and word. 168 | sp_after_decltype = force # ignore/add/remove/force 169 | 170 | # Add or remove space before '<'. 171 | sp_before_angle = remove # ignore/add/remove/force 172 | 173 | # Add or remove space inside '<' and '>'. 174 | sp_inside_angle = remove # ignore/add/remove/force 175 | 176 | # Add or remove space inside '<>'. 177 | sp_inside_angle_empty = remove # ignore/add/remove/force 178 | 179 | # Add or remove space between '>' and ':'. 180 | sp_angle_colon = force # ignore/add/remove/force 181 | 182 | # Add or remove space after '>'. 183 | sp_after_angle = force # ignore/add/remove/force 184 | 185 | # Add or remove space between '>' and '(' as found in 'new List<byte>(foo);'. 186 | sp_angle_paren = add # ignore/add/remove/force 187 | 188 | # Add or remove space between '>' and '()' as found in 'new List<byte>();'. 189 | sp_angle_paren_empty = add # ignore/add/remove/force 190 | 191 | # Add or remove space between '>' and a word as in 'List<byte> m;' or 192 | # 'template <typename T> static ...'. 193 | sp_angle_word = force # ignore/add/remove/force 194 | 195 | # Add or remove space between '>' and '>' in '>>' (template stuff). 196 | # 197 | # Default: add 198 | sp_angle_shift = remove # ignore/add/remove/force 199 | 200 | # (C++11) Permit removal of the space between '>>' in 'foo<bar<int> >'. Note 201 | # that sp_angle_shift cannot remove the space without this option. 202 | sp_permit_cpp11_shift = true # true/false 203 | 204 | # Add or remove space before '(' of control statements ('if', 'for', 'switch', 205 | # 'while', etc.). 206 | sp_before_sparen = add # ignore/add/remove/force 207 | 208 | # Add or remove space inside '(' and ')' of control statements. 209 | sp_inside_sparen = remove # ignore/add/remove/force 210 | 211 | # Add or remove space between ')' and '{' of of control statements. 212 | sp_sparen_brace = force # ignore/add/remove/force 213 | 214 | # Add or remove space before empty statement ';' on 'if', 'for' and 'while'. 215 | sp_special_semi = remove # ignore/add/remove/force 216 | 217 | # Add or remove space before ';' in non-empty 'for' statements. 218 | sp_before_semi_for = remove # ignore/add/remove/force 219 | 220 | # Add or remove space before a semicolon of an empty part of a for statement. 221 | sp_before_semi_for_empty = remove # ignore/add/remove/force 222 | 223 | # Add or remove space after ';', except when followed by a comment. 224 | # 225 | # Default: add 226 | sp_after_semi = remove # ignore/add/remove/force 227 | 228 | # Add or remove space after ';' in non-empty 'for' statements. 229 | # 230 | # Default: force 231 | sp_after_semi_for = force # ignore/add/remove/force 232 | 233 | # Add or remove space after the final semicolon of an empty part of a for 234 | # statement, as in 'for ( ; ; <here> )'. 235 | sp_after_semi_for_empty = remove # ignore/add/remove/force 236 | 237 | # Add or remove space before '[' (except '[]'). 238 | sp_before_square = remove # ignore/add/remove/force 239 | 240 | # Add or remove space before '[' for a variable definition. 241 | # 242 | # Default: remove 243 | sp_before_vardef_square = remove # ignore/add/remove/force 244 | 245 | # Add or remove space before '[]'. 246 | sp_before_squares = add # ignore/add/remove/force 247 | 248 | # Add or remove space before C++17 structured bindings. 249 | sp_cpp_before_struct_binding = force # ignore/add/remove/force 250 | 251 | # Add or remove space inside a non-empty '[' and ']'. 252 | sp_inside_square = remove # ignore/add/remove/force 253 | 254 | # Add or remove space after ',', i.e. 'a,b' vs. 'a, b'. 255 | sp_after_comma = force # ignore/add/remove/force 256 | 257 | # Add or remove space before the variadic '...' when preceded by a 258 | # non-punctuator. 259 | sp_before_ellipsis = remove # ignore/add/remove/force 260 | 261 | # Add or remove space between a type and '...'. 262 | sp_type_ellipsis = remove # ignore/add/remove/force 263 | 264 | # Add or remove space between ')' and '...'. 265 | sp_paren_ellipsis = remove # ignore/add/remove/force 266 | 267 | # Add or remove space between ')' and a qualifier such as 'const'. 268 | sp_paren_qualifier = force # ignore/add/remove/force 269 | 270 | # Add or remove space between ')' and 'noexcept'. 271 | sp_paren_noexcept = force # ignore/add/remove/force 272 | 273 | # Add or remove space after class ':'. 274 | sp_after_class_colon = force # ignore/add/remove/force 275 | 276 | # Add or remove space before class ':'. 277 | sp_before_class_colon = force # ignore/add/remove/force 278 | 279 | # Add or remove space after class constructor ':'. 280 | sp_after_constr_colon = force # ignore/add/remove/force 281 | 282 | # Add or remove space before class constructor ':'. 283 | sp_before_constr_colon = force # ignore/add/remove/force 284 | 285 | # Add or remove space between 'operator' and operator sign. 286 | sp_after_operator = force # ignore/add/remove/force 287 | 288 | # Add or remove space after C/D cast, i.e. 'cast(int)a' vs. 'cast(int) a' or 289 | # '(int)a' vs. '(int) a'. 290 | sp_after_cast = remove # ignore/add/remove/force 291 | 292 | # Add or remove spaces inside cast parentheses. 293 | sp_inside_paren_cast = remove # ignore/add/remove/force 294 | 295 | # Add or remove space between the type and open parenthesis in a C++ cast, 296 | # i.e. 'int(exp)' vs. 'int (exp)'. 297 | sp_cpp_cast_paren = remove # ignore/add/remove/force 298 | 299 | # Add or remove space between 'sizeof' and '('. 300 | sp_sizeof_paren = add # ignore/add/remove/force 301 | 302 | # Add or remove space between 'sizeof' and '...'. 303 | sp_sizeof_ellipsis = remove # ignore/add/remove/force 304 | 305 | # Add or remove space between 'sizeof...' and '('. 306 | sp_sizeof_ellipsis_paren = add # ignore/add/remove/force 307 | 308 | # Add or remove space between 'decltype' and '('. 309 | sp_decltype_paren = add # ignore/add/remove/force 310 | 311 | # Add or remove space after open brace in an unnamed temporary 312 | # direct-list-initialization. 313 | sp_after_type_brace_init_lst_open = remove # ignore/add/remove/force 314 | 315 | # Add or remove space before close brace in an unnamed temporary 316 | # direct-list-initialization. 317 | sp_before_type_brace_init_lst_close = remove # ignore/add/remove/force 318 | 319 | # Add or remove space inside '{}'. 320 | sp_inside_braces_empty = remove # ignore/add/remove/force 321 | 322 | # Add or remove space around trailing return operator '->'. 323 | sp_trailing_return = add # ignore/add/remove/force 324 | 325 | # Add or remove space between type and open brace of an unnamed temporary 326 | # direct-list-initialization. 327 | sp_type_brace_init_lst = remove # ignore/add/remove/force 328 | 329 | # Add or remove space between function name and '(' on function declaration. 330 | sp_func_proto_paren = add # ignore/add/remove/force 331 | 332 | # Add or remove space between function name and '()' on function declaration 333 | # without parameters. 334 | sp_func_proto_paren_empty = add # ignore/add/remove/force 335 | 336 | # Add or remove space between function name and '(' with a typedef specifier. 337 | sp_func_type_paren = add # ignore/add/remove/force 338 | 339 | # Add or remove space between alias name and '(' of a non-pointer function type typedef. 340 | sp_func_def_paren = add # ignore/add/remove/force 341 | 342 | # Add or remove space between function name and '()' on function definition 343 | # without parameters. 344 | sp_func_def_paren_empty = add # ignore/add/remove/force 345 | 346 | # Add or remove space inside empty function '()'. 347 | # Overrides sp_after_angle unless use_sp_after_angle_always is set to true. 348 | sp_inside_fparens = remove # ignore/add/remove/force 349 | 350 | # Add or remove space inside function '(' and ')'. 351 | sp_inside_fparen = remove # ignore/add/remove/force 352 | 353 | # Add or remove space inside the first parentheses in a function type, as in 354 | # 'void (*x)(...)'. 355 | sp_inside_tparen = add # ignore/add/remove/force 356 | 357 | # Add or remove space between ']' and '(' when part of a function call. 358 | sp_square_fparen = remove # ignore/add/remove/force 359 | 360 | # Add or remove space between ')' and '{' of function. 361 | sp_fparen_brace = force # ignore/add/remove/force 362 | 363 | # Add or remove space between function name and '(' on function calls. 364 | sp_func_call_paren = remove # ignore/add/remove/force 365 | 366 | # Add or remove space between a constructor/destructor and the open 367 | # parenthesis. 368 | sp_func_class_paren = remove # ignore/add/remove/force 369 | 370 | # Add or remove space between a constructor without parameters or destructor 371 | # and '()'. 372 | sp_func_class_paren_empty = remove # ignore/add/remove/force 373 | 374 | # Add or remove space between 'return' and '('. 375 | sp_return_paren = force # ignore/add/remove/force 376 | 377 | # Add or remove space between 'return' and '{'. 378 | sp_return_brace = force # ignore/add/remove/force 379 | 380 | # Add or remove space between '__attribute__' and '('. 381 | sp_attribute_paren = remove # ignore/add/remove/force 382 | 383 | # Add or remove space between 'defined' and '(' in '#if defined (FOO)'. 384 | sp_defined_paren = force # ignore/add/remove/force 385 | 386 | # Add or remove space between 'throw' and '(' in 'throw (something)'. 387 | sp_throw_paren = force # ignore/add/remove/force 388 | 389 | # Add or remove space between 'throw' and anything other than '(' as in 390 | # '@throw [...];'. 391 | sp_after_throw = force # ignore/add/remove/force 392 | 393 | # Add or remove space between 'catch' and '(' in 'catch (something) { }'. 394 | # If set to ignore, sp_before_sparen is used. 395 | sp_catch_paren = force # ignore/add/remove/force 396 | 397 | # Add or remove space between a macro function ')' and its definition. 398 | sp_macro_func = add # ignore/add/remove/force 399 | 400 | # Add or remove space between 'else' and '{' if on the same line. 401 | sp_else_brace = force # ignore/add/remove/force 402 | 403 | # Add or remove space between '}' and 'else' if on the same line. 404 | sp_brace_else = force # ignore/add/remove/force 405 | 406 | # Add or remove space between '}' and the name of a typedef on the same line. 407 | sp_brace_typedef = force # ignore/add/remove/force 408 | 409 | # Add or remove space before the '{' of a 'catch' statement, if the '{' and 410 | # 'catch' are on the same line, as in 'catch (decl) <here> {'. 411 | sp_catch_brace = force # ignore/add/remove/force 412 | 413 | # Add or remove space between '}' and 'catch' if on the same line. 414 | sp_brace_catch = force # ignore/add/remove/force 415 | 416 | # Add or remove space between 'try' and '{' if on the same line. 417 | sp_try_brace = force # ignore/add/remove/force 418 | 419 | # Add or remove space between a variable and '{' for C++ uniform 420 | # initialization. 421 | sp_word_brace_init_lst = remove # ignore/add/remove/force 422 | 423 | # Add or remove space before the '::' operator. 424 | sp_before_dc = remove # ignore/add/remove/force 425 | 426 | # Add or remove space after the '::' operator. 427 | sp_after_dc = remove # ignore/add/remove/force 428 | 429 | # Add or remove space before a backslash-newline at the end of a line. 430 | # 431 | # Default: add 432 | sp_before_nl_cont = add # ignore/add/remove/force 433 | 434 | # Add or remove space around the ':' in 'b ? t : f'. 435 | sp_cond_colon = force # ignore/add/remove/force 436 | 437 | # Add or remove space around the '?' in 'b ? t : f'. 438 | sp_cond_question = force # ignore/add/remove/force 439 | 440 | # In the abbreviated ternary form '(a ?: b)', add or remove space between '?' 441 | # and ':'. 442 | # 443 | # Overrides all other sp_cond_* options. 444 | sp_cond_ternary_short = remove # ignore/add/remove/force 445 | 446 | # Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make 447 | # sense here. 448 | sp_case_label = force # ignore/add/remove/force 449 | 450 | # Add or remove space after ':' in a Java/C++11 range-based 'for', 451 | # as in 'for (Type var : expr)'. 452 | sp_after_for_colon = force # ignore/add/remove/force 453 | 454 | # Add or remove space before ':' in a Java/C++11 range-based 'for', 455 | # as in 'for (Type var : expr)'. 456 | sp_before_for_colon = force # ignore/add/remove/force 457 | 458 | # Add or remove space after the opening of a C++ comment, 459 | # i.e. '// A' vs. '//A'. 460 | sp_cmt_cpp_start = force # ignore/add/remove/force 461 | 462 | # Add or remove space between #else or #endif and a trailing comment. 463 | sp_endif_cmt = force # ignore/add/remove/force 464 | 465 | # Add or remove space after 'new', 'delete' and 'delete[]'. 466 | sp_after_new = force # ignore/add/remove/force 467 | 468 | # Add or remove space between 'new' and '(' in 'new()'. 469 | sp_between_new_paren = remove # ignore/add/remove/force 470 | 471 | # Add or remove space between ')' and type in 'new(foo) BAR'. 472 | sp_after_newop_paren = force # ignore/add/remove/force 473 | 474 | # Add or remove space inside parenthesis of the new operator 475 | # as in 'new(foo) BAR'. 476 | sp_inside_newop_paren = remove # ignore/add/remove/force 477 | 478 | # Add or remove space before a trailing or embedded comment. 479 | sp_before_tr_emb_cmt = force # ignore/add/remove/force 480 | 481 | # Number of spaces before a trailing or embedded comment. 482 | sp_num_before_tr_emb_cmt = 1 # unsigned number 483 | 484 | # 485 | # Indenting options 486 | # 487 | 488 | # The number of columns to indent per level. Usually 2, 3, 4, or 8. 489 | # 490 | # Default: 8 491 | indent_columns = 4 # unsigned number 492 | 493 | # The continuation indent. If non-zero, this overrides the indent of '(', '[' 494 | # and '=' continuation indents. Negative values are OK; negative value is 495 | # absolute and not increased for each '(' or '[' level. 496 | # 497 | # For FreeBSD, this is set to 4. 498 | indent_continue = 0 # number 499 | 500 | # How to use tabs when indenting code. 501 | # 502 | # 0: Spaces only 503 | # 1: Indent with tabs to brace level, align with spaces (default) 504 | # 2: Indent and align with tabs, using spaces when not on a tabstop 505 | # 506 | # Default: 1 507 | indent_with_tabs = 0 # unsigned number 508 | 509 | # Whether to indent strings broken by '\' so that they line up. 510 | indent_align_string = true # true/false 511 | 512 | # Whether the 'extern "C"' body is indented. 513 | indent_extern = true # true/false 514 | 515 | # Whether the 'class' body is indented. 516 | indent_class = true # true/false 517 | 518 | # Whether to indent the stuff after a leading base class colon. 519 | indent_class_colon = false # true/false 520 | 521 | # Whether to indent based on a class colon instead of the stuff after the 522 | # colon. Requires indent_class_colon=true. 523 | indent_class_on_colon = true # true/false 524 | 525 | # Whether to indent the stuff after a leading class initializer colon. 526 | indent_constr_colon = false # true/false 527 | 528 | # Virtual indent from the ':' for member initializers. 529 | # 530 | # Default: 2 531 | indent_ctor_init_leading = 2 # unsigned number 532 | 533 | # Whether to indent continued variable declarations instead of aligning. 534 | indent_var_def_cont = false # true/false 535 | 536 | # Whether to indent continued function call parameters one indent level, 537 | # rather than aligning parameters under the open parenthesis. 538 | indent_func_call_param = false # true/false 539 | 540 | # Whether to indent continued function definition parameters one indent level, 541 | # rather than aligning parameters under the open parenthesis. 542 | indent_func_def_param = false # true/false 543 | 544 | # Whether to indent continued function call prototype one indent level, 545 | # rather than aligning parameters under the open parenthesis. 546 | indent_func_proto_param = false # true/false 547 | 548 | # Whether to indent continued function call declaration one indent level, 549 | # rather than aligning parameters under the open parenthesis. 550 | indent_func_class_param = false # true/false 551 | 552 | # Whether to indent continued class variable constructors one indent level, 553 | # rather than aligning parameters under the open parenthesis. 554 | indent_func_ctor_var_param = false # true/false 555 | 556 | # Whether to indent continued template parameter list one indent level, 557 | # rather than aligning parameters under the open parenthesis. 558 | indent_template_param = false # true/false 559 | 560 | # Whether lines broken at '.' or '->' should be indented by a single indent. 561 | # The indent_member option will not be effective if this is set to true. 562 | indent_member_single = true # true/false 563 | 564 | # Whether to indent trailing single line ('//') comments relative to the code 565 | # instead of trying to keep the same absolute column. 566 | indent_relative_single_line_comments = true # true/false 567 | 568 | # Spaces to indent 'case' from 'switch'. Usually 0 or indent_columns. 569 | indent_switch_case = 0 # unsigned number 570 | 571 | # Spaces to shift the 'case' line, without affecting any other lines. 572 | # Usually 0. 573 | indent_case_shift = 2 # unsigned number 574 | 575 | # How to indent access specifiers that are followed by a 576 | # colon. 577 | # 578 | # >0: Absolute column where 1 is the leftmost column 579 | # <=0: Subtract from brace indent 580 | # 581 | # Default: 1 582 | indent_access_spec = -2 # number 583 | 584 | # How to indent a close parenthesis after a newline. 585 | # 586 | # 0: Indent to body level (default) 587 | # 1: Align under the open parenthesis 588 | # 2: Indent to the brace level 589 | indent_paren_close = 1 # unsigned number 590 | 591 | # Whether to align continued statements at the '='. If false or if the '=' is 592 | # followed by a newline, the next line is indent one tab. 593 | # 594 | # Default: true 595 | indent_align_assign = false # true/false 596 | 597 | # Whether to align continued statements at the '('. If false or the '(' is 598 | # followed by a newline, the next line indent is one tab. 599 | # 600 | # Default: true 601 | indent_align_paren = false # true/false 602 | 603 | # How to indent after a brace followed by another token (not a newline). 604 | # true: indent all contained lines to match the token 605 | # false: indent all contained lines to match the brace 606 | # 607 | # Default: true 608 | indent_token_after_brace = false # true/false 609 | 610 | # Whether to indent the body of a C++11 lambda. 611 | indent_cpp_lambda_body = false # true/false 612 | # 613 | # 614 | # Newline adding and removing options 615 | # 616 | 617 | # Whether to collapse empty blocks between '{' and '}'. 618 | nl_collapse_empty_body = false # true/false 619 | 620 | # Don't split one-line braced assignments, as in 'foo_t f = { 1, 2 };'. 621 | nl_assign_leave_one_liners = true # true/false 622 | 623 | # Don't split one-line C++11 lambdas, as in '[]() { return 0; }'. 624 | nl_cpp_lambda_leave_one_liners = false # true/false 625 | 626 | # Add or remove newlines at the start of the file. 627 | nl_start_of_file = remove # ignore/add/remove/force 628 | 629 | # Add or remove newline at the end of the file. 630 | nl_end_of_file = remove # ignore/add/remove/force 631 | 632 | # The minimum number of newlines at the end of the file (only used if 633 | # nl_end_of_file is 'add' or 'force'). 634 | nl_end_of_file_min = 1 # unsigned number 635 | 636 | # Add or remove newline between '=' and '{'. 637 | nl_assign_brace = add # ignore/add/remove/force 638 | 639 | # Add or remove newline between a function call's ')' and '{', as in 640 | # 'list_for_each(item, &list) { }'. 641 | nl_fcall_brace = add # ignore/add/remove/force 642 | 643 | # Add or remove newline between 'enum' and '{'. 644 | nl_enum_brace = add # ignore/add/remove/force 645 | 646 | # Add or remove newline between 'enum' and 'class'. 647 | nl_enum_class = add # ignore/add/remove/force 648 | 649 | # Add or remove newline between 'enum class' and the identifier. 650 | nl_enum_class_identifier = force # ignore/add/remove/force 651 | 652 | # Add or remove newline between 'enum class' type and ':'. 653 | nl_enum_identifier_colon = remove # ignore/add/remove/force 654 | 655 | # Add or remove newline between 'struct and '{'. 656 | nl_struct_brace = add # ignore/add/remove/force 657 | 658 | # Add or remove newline between 'union' and '{'. 659 | nl_union_brace = add # ignore/add/remove/force 660 | 661 | # Add or remove newline between 'if' and '{'. 662 | nl_if_brace = ignore # ignore/add/remove/force 663 | 664 | # Add or remove newline between '}' and 'else'. 665 | nl_brace_else = add # ignore/add/remove/force 666 | 667 | # Add or remove newline between 'else if' and '{'. If set to ignore, 668 | # nl_if_brace is used instead. 669 | nl_elseif_brace = add # ignore/add/remove/force 670 | 671 | # Add or remove newline between 'else' and '{'. 672 | nl_else_brace = add # ignore/add/remove/force 673 | 674 | # Add or remove newline between 'else' and 'if'. 675 | nl_else_if = add # ignore/add/remove/force 676 | 677 | # Add or remove newline before '{' opening brace 678 | nl_before_opening_brace_func_class_def = add # ignore/add/remove/force 679 | 680 | # Add or remove newline before 'if'/'else if' closing parenthesis. 681 | nl_before_if_closing_paren = remove # ignore/add/remove/force 682 | 683 | # Add or remove newline between 'try' and '{'. 684 | nl_try_brace = add # ignore/add/remove/force 685 | 686 | # Add or remove newline between 'for' and '{'. 687 | nl_for_brace = add # ignore/add/remove/force 688 | 689 | # Add or remove newline before the '{' of a 'catch' statement, as in 690 | # 'catch (decl) <here> {'. 691 | nl_catch_brace = add # ignore/add/remove/force 692 | 693 | # Add or remove newline between '}' and 'catch'. 694 | nl_brace_catch = add # ignore/add/remove/force 695 | 696 | # Add or remove newline between '}' and ')' in a function invocation. 697 | nl_brace_fparen = remove # ignore/add/remove/force 698 | 699 | # Add or remove newline between 'while' and '{'. 700 | nl_while_brace = add # ignore/add/remove/force 701 | 702 | # Add or remove newline between two open or close braces. Due to general 703 | # newline/brace handling, REMOVE may not work. 704 | nl_brace_brace = add # ignore/add/remove/force 705 | 706 | # Add or remove newline between 'do' and '{'. 707 | nl_do_brace = add # ignore/add/remove/force 708 | 709 | # Add or remove newline between '}' and 'while' of 'do' statement. 710 | nl_brace_while = add # ignore/add/remove/force 711 | 712 | # Add or remove newline between 'switch' and '{'. 713 | nl_switch_brace = add # ignore/add/remove/force 714 | 715 | # Force a newline in a define after the macro name for multi-line defines. 716 | nl_multi_line_define = true # true/false 717 | 718 | # Whether to add a newline before 'case', and a blank line before a 'case' 719 | # statement that follows a ';' or '}'. 720 | nl_before_case = true # true/false 721 | 722 | # Whether to add a newline after a 'case' statement. 723 | nl_after_case = true # true/false 724 | 725 | # Add or remove newline between 'namespace' and '{'. 726 | nl_namespace_brace = true # ignore/add/remove/force 727 | 728 | # Add or remove newline after 'template<...>' of a template class. 729 | nl_template_class = force # ignore/add/remove/force 730 | 731 | # Add or remove newline after 'template<...>' of a template function. 732 | nl_template_func = force # ignore/add/remove/force 733 | 734 | # Add or remove newline between 'class' and '{'. 735 | nl_class_brace = force # ignore/add/remove/force 736 | 737 | # Add or remove newline before first element, after comma, and after last 738 | # element, in 'enum'. 739 | nl_enum_own_lines = add # ignore/add/remove/force 740 | 741 | # Add or remove newline between return type and function name in a function 742 | # definition. 743 | # might be modified by nl_func_leave_one_liners 744 | nl_func_type_name = add # ignore/add/remove/force 745 | 746 | # Add or remove newline between class specification and '::' 747 | # in 'void A::f() { }'. Only appears in separate member implementation (does 748 | # not appear with in-line implementation). 749 | nl_func_class_scope = remove # ignore/add/remove/force 750 | 751 | # Add or remove newline between function scope and name, as in 752 | # 'void A :: <here> f() { }'. 753 | nl_func_scope_name = add # ignore/add/remove/force 754 | 755 | # Add or remove newline between return type and function name in a prototype. 756 | nl_func_proto_type_name = add # ignore/add/remove/force 757 | 758 | # Add or remove newline between a function name and the opening '(' in the 759 | # declaration. 760 | nl_func_paren = remove # ignore/add/remove/force 761 | 762 | # Add or remove newline between a function name and the opening '(' in the 763 | # definition. 764 | nl_func_def_paren = remove # ignore/add/remove/force 765 | 766 | # Add or remove newline between a function name and the opening '(' in the 767 | # call. 768 | nl_func_call_paren = remove # ignore/add/remove/force 769 | 770 | # Add or remove newline after each ',' in a function declaration. 771 | nl_func_decl_args = ignore # ignore/add/remove/force 772 | 773 | # Add or remove newline after each ',' in a function definition. 774 | nl_func_def_args = ignore # ignore/add/remove/force 775 | 776 | # Add or remove newline after each ',' in a function call. 777 | nl_func_call_args = ignore # ignore/add/remove/force 778 | 779 | # Add or remove newline before the ')' in a function declaration. 780 | nl_func_decl_end = remove # ignore/add/remove/force 781 | 782 | # Add or remove newline before the ')' in a function definition. 783 | nl_func_def_end = remove # ignore/add/remove/force 784 | 785 | # Add or remove newline between '()' in a function declaration. 786 | nl_func_decl_empty = remove # ignore/add/remove/force 787 | 788 | # Add or remove newline between '()' in a function definition. 789 | nl_func_def_empty = remove # ignore/add/remove/force 790 | 791 | # Add or remove newline between '()' in a function call. 792 | nl_func_call_empty = remove # ignore/add/remove/force 793 | 794 | # Whether to add a newline before ')' in a function call. 795 | nl_func_call_end = remove # ignore/add/remove/force 796 | 797 | # Add or remove newline between function signature and '{'. 798 | nl_fdef_brace = true # ignore/add/remove/force 799 | 800 | # Add or remove newline between C++11 lambda signature and '{'. 801 | nl_cpp_ldef_brace = add # ignore/add/remove/force 802 | 803 | # Whether to add a newline after semicolons, except in 'for' statements. 804 | nl_after_semicolon = true # true/false 805 | 806 | # Whether to add a newline after '{'. This also adds a newline before the 807 | # matching '}'. 808 | nl_after_brace_open = true # true/false 809 | 810 | # Whether to add a newline between the open brace and a trailing single-line 811 | # comment. Requires nl_after_brace_open=true. 812 | nl_after_brace_open_cmt = true # true/false 813 | 814 | # Whether to add a newline after '}'. Does not apply if followed by a 815 | # necessary ';'. 816 | nl_after_brace_close = true # true/false 817 | 818 | # Whether to add a newline after a virtual brace close, 819 | # as in 'if (foo) a++; <here> return;'. 820 | nl_after_vbrace_close = true # true/false 821 | 822 | # Add or remove newline between the close brace and identifier, 823 | # as in 'struct { int a; } <here> b;'. Affects enumerations, unions and 824 | # structures. If set to ignore, uses nl_after_brace_close. 825 | nl_brace_struct_var = remove # ignore/add/remove/force 826 | 827 | # Add or remove blank line after 'if' statement. Add/Force work only if the 828 | # next token is not a closing brace. 829 | nl_after_if = force # ignore/add/remove/force 830 | 831 | # Add or remove blank line after 'for' statement. 832 | nl_after_for = force # ignore/add/remove/force 833 | 834 | # Add or remove blank line after 'while' statement. 835 | nl_after_while = force # ignore/add/remove/force 836 | 837 | # Add or remove blank line after 'switch' statement. 838 | nl_after_switch = force # ignore/add/remove/force 839 | 840 | # Add or remove blank line after 'do/while' statement. 841 | nl_after_do = force # ignore/add/remove/force 842 | 843 | # Whether to put a blank line before 'return' statements, unless after an open 844 | # brace. 845 | nl_before_return = true # true/false 846 | 847 | # Whether to force a newline before '}' of a 'struct'/'union'/'enum'. 848 | # (Lower priority than eat_blanks_before_close_brace.) 849 | nl_ds_struct_enum_close_brace = true # true/false 850 | 851 | 852 | # Blank line options 853 | # 854 | 855 | # The maximum number of consecutive newlines (3 = 2 blank lines). 856 | nl_max = 2 # unsigned number 857 | 858 | # The maximum number of consecutive newlines in a function. 859 | nl_max_blank_in_func = 2 # unsigned number 860 | 861 | # The number of newlines after '}' of a multi-line function body. 862 | nl_after_func_body = 2 # unsigned number 863 | 864 | # The number of newlines after '}' of a multi-line function body in a class 865 | # declaration. Also affects class constructors/destructors. 866 | # 867 | # Overrides nl_after_func_body. 868 | nl_after_func_body_class = 2 # unsigned number 869 | 870 | # The number of newlines after '}' or ';' of a struct/enum/union definition. 871 | nl_after_struct = 2 # unsigned number 872 | 873 | # The number of newlines after '}' or ';' of a class definition. 874 | nl_after_class = 2 # unsigned number 875 | 876 | # The number of newlines after '}' of a namespace. 877 | nl_after_namespace = 2 # unsigned number 878 | 879 | # The number of newlines before an access specifier label. This also includes 880 | # the Qt-specific 'signals:' and 'slots:'. Will not change the newline count 881 | # if after a brace open. 882 | # 883 | # 0: No change (default). 884 | nl_before_access_spec = 2 # unsigned number 885 | 886 | # The number of newlines after a try-catch-finally block that isn't followed 887 | # by a brace close. 888 | # 889 | # 0: No change (default). 890 | nl_after_try_catch_finally = 2 # unsigned number 891 | 892 | # Whether to remove blank lines after '{'. 893 | eat_blanks_after_open_brace = true # true/false 894 | 895 | # Whether to remove blank lines before '}'. 896 | eat_blanks_before_close_brace = true # true/false 897 | 898 | # 899 | # Positioning options 900 | # 901 | 902 | # The position of arithmetic operators in wrapped expressions. 903 | pos_arith = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force 904 | 905 | # The position of assignment in wrapped expressions. Do not affect '=' 906 | # followed by '{'. 907 | pos_assign = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force 908 | 909 | # The position of Boolean operators in wrapped expressions. 910 | pos_bool = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force 911 | 912 | # The position of comparison operators in wrapped expressions. 913 | pos_compare = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force 914 | 915 | # The position of conditional operators, as in the '?' and ':' of 916 | # 'expr ? stmt : stmt', in wrapped expressions. 917 | pos_conditional = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force 918 | 919 | # The position of the comma in wrapped expressions. 920 | pos_comma = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force 921 | 922 | # The position of the comma in enum entries. 923 | pos_enum_comma = trail_force # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force 924 | 925 | # The position of the comma in the base class list if there is more than one 926 | # line. Affects nl_class_init_args. 927 | pos_class_comma = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force 928 | 929 | # The position of the comma in the constructor initialization list. 930 | # Related to nl_constr_colon, nl_constr_init_args and pos_constr_colon. 931 | pos_constr_comma = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force 932 | 933 | # The position of trailing/leading class colon, between class and base class 934 | # list. Affects nl_class_colon. 935 | pos_class_colon = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force 936 | 937 | # The position of colons between constructor and member initialization. 938 | # Related to nl_constr_colon, nl_constr_init_args and pos_constr_comma. 939 | pos_constr_colon = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force 940 | 941 | # 942 | # Code alignment options (not left column spaces/tabs) 943 | # 944 | 945 | # The span for aligning on '=' in assignments. 946 | # 947 | # 0: Don't align (default). 948 | align_assign_span = 0 # unsigned number 949 | align_assign_thresh = -4 # number 950 | 951 | align_enum_equ_span = 4 # unsigned number 952 | align_enum_equ_thresh = -20 # number 953 | 954 | align_number_right = true # true/false 955 | # 956 | # Line splitting options 957 | # 958 | 959 | # Try to limit code width to N columns. 960 | code_width = 0 # unsigned number 961 | 962 | # Whether to fully split long 'for' statements at semi-colons. 963 | ls_for_split_full = true # true/false 964 | 965 | # Whether to fully split long function prototypes/calls at commas. 966 | # The option ls_code_width has priority over the option ls_func_split_full. 967 | ls_func_split_full = false # true/false 968 | 969 | # Whether to split lines as close to code_width as possible and ignore some 970 | # groupings. 971 | # The option ls_code_width has priority over the option ls_func_split_full. 972 | ls_code_width = false # true/false 973 | 974 | # 975 | # Comment modification options 976 | # 977 | 978 | # Try to wrap comments at N columns. 979 | cmt_width = 85 # unsigned number 980 | 981 | # How to reflow comments. 982 | # 983 | # 0: No reflowing (apart from the line wrapping due to cmt_width) (default) 984 | # 1: No touching at all 985 | # 2: Full reflow 986 | cmt_reflow_mode = 2 # unsigned number 987 | 988 | # Whether to convert all tabs to spaces in comments. If false, tabs in 989 | # comments are left alone, unless used for indenting. 990 | cmt_convert_tab_to_spaces = true # true/false 991 | 992 | # Whether to group c-comments that look like they are in a block. 993 | cmt_c_group = true # true/false 994 | 995 | # Whether to put a star on subsequent comment lines. 996 | cmt_star_cont = true # true/false 997 | 998 | # Whether to put an empty '/*' on the first line of the combined c-comment. 999 | cmt_c_nl_start = true # true/false 1000 | 1001 | # Whether to add a newline before the closing '*/' of the combined c-comment. 1002 | cmt_c_nl_end = true # true/false 1003 | 1004 | # The number of spaces to insert at the start of subsequent comment lines. 1005 | cmt_sp_before_star_cont = 0 # unsigned number 1006 | 1007 | # The number of spaces to insert after the star on subsequent comment lines. 1008 | cmt_sp_after_star_cont = 1 # unsigned number 1009 | 1010 | # 1011 | # Code modifying options (non-whitespace) 1012 | # 1013 | 1014 | # Add or remove braces on a single-line 'do' statement. 1015 | mod_full_brace_do = force # ignore/add/remove/force 1016 | 1017 | # Add or remove braces on a single-line 'for' statement. 1018 | mod_full_brace_for = force # ignore/add/remove/force 1019 | 1020 | # (Pawn) Add or remove braces on a single-line function definition. 1021 | mod_full_brace_function = force # ignore/add/remove/force 1022 | 1023 | # Add or remove braces on a single-line 'if' statement. Braces will not be 1024 | # removed if the braced statement contains an 'else'. 1025 | mod_full_brace_if = force # ignore/add/remove/force 1026 | 1027 | # Whether to add braces to all blocks of an 'if'/'else if'/'else' chain. 1028 | # If true, mod_full_brace_if_chain will only remove braces from an 'if' that 1029 | # does not have an 'else if' or 'else'. 1030 | mod_full_brace_if_chain_only = true # true/false 1031 | 1032 | # Add or remove braces on single-line 'while' statement. 1033 | mod_full_brace_while = force # ignore/add/remove/force 1034 | 1035 | # Whether to fully parenthesize Boolean expressions in 'while' and 'if' 1036 | # statement, as in 'if (a && b > c)' => 'if (a && (b > c))'. 1037 | mod_full_paren_if_bool = true # true/false 1038 | 1039 | # Whether to remove superfluous semicolons. 1040 | mod_remove_extra_semicolon = true # true/false 1041 | 1042 | # If an #ifdef body exceeds the specified number of newlines and doesn't have 1043 | # a comment after the #endif, a comment will be added. 1044 | mod_add_long_ifdef_endif_comment = 0 # unsigned number 1045 | 1046 | # If an #ifdef or #else body exceeds the specified number of newlines and 1047 | # doesn't have a comment after the #else, a comment will be added. 1048 | mod_add_long_ifdef_else_comment = 0 # unsigned number 1049 | 1050 | # Whether to remove a void 'return;' that appears as the last statement in a 1051 | # function. 1052 | mod_remove_empty_return = false # true/false 1053 | 1054 | # Add or remove the comma after the last value of an enumeration. 1055 | mod_enum_last_comma = force # ignore/add/remove/force 1056 | 1057 | # 1058 | # Preprocessor options 1059 | # 1060 | 1061 | # Add or remove indentation of preprocessor directives inside #if blocks 1062 | # at brace level 0 (file-level). 1063 | pp_indent = add # ignore/add/remove/force 1064 | 1065 | # Whether to indent the code between #if, #else and #endif. 1066 | pp_if_indent_code = false # true/false 1067 | 1068 | # Use or Do not Use options 1069 | # 1070 | 1071 | # true: indent_func_call_param will be used (default) 1072 | # false: indent_func_call_param will NOT be used 1073 | # 1074 | # Default: true 1075 | use_indent_func_call_param = true # true/false 1076 | 1077 | # The value of the indentation for a continuation line is calculated 1078 | # differently if the statement is: 1079 | # - a declaration: your case with QString fileName ... 1080 | # - an assignment: your case with pSettings = new QSettings( ... 1081 | # 1082 | # At the second case the indentation value might be used twice: 1083 | # - at the assignment 1084 | # - at the function call (if present) 1085 | # 1086 | # To prevent the double use of the indentation value, use this option with the 1087 | # value 'true'. 1088 | # 1089 | # true: indent_continue will be used only once 1090 | # false: indent_continue will be used every time (default) 1091 | use_indent_continue_only_once = true # true/false 1092 | 1093 | # The value might be used twice: 1094 | # - at the assignment 1095 | # - at the opening brace 1096 | # 1097 | # To prevent the double use of the indentation value, use this option with the 1098 | # value 'true'. 1099 | # 1100 | # true: indentation will be used only once 1101 | # false: indentation will be used every time (default) 1102 | indent_cpp_lambda_only_once = false # true/false 1103 | 1104 | # Whether sp_after_angle takes precedence over sp_inside_fparen. This was the 1105 | # historic behavior, but is probably not the desired behavior, so this is off 1106 | # by default. 1107 | use_sp_after_angle_always = false # true/false 1108 | -------------------------------------------------------------------------------- /dbus_interface_backend.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************* 2 | * This file is licensed under the MIT license. 3 | * Copyright (C) 2019 - 2020 Damian Ivanov <damianatorrpm@gmail.com> 4 | ********************************************************************/ 5 | #define DBUS_PLUGIN_DEBUG TRUE 6 | #define DBUS_PLUGIN_WARN TRUE 7 | 8 | extern "C" { 9 | #define class class_t 10 | #define static 11 | #include <X11/Xatom.h> 12 | #include <wlr/xwayland.h> 13 | #include <xcb/res.h> 14 | #include <xcb/xcb.h> 15 | // #include <xwayland/xwm.h> 16 | #undef static 17 | #undef class 18 | #include <sys/socket.h> 19 | #include <wlr/types/wlr_idle.h> 20 | }; 21 | 22 | #include <gio/gio.h> 23 | #include <ctime> 24 | #include <iostream> 25 | #include <list> 26 | #include <set> 27 | 28 | #include <unistd.h> 29 | 30 | #include "dbus_scale_filter.hpp" 31 | #include "wayfire/view-transform.hpp" 32 | #include <wayfire/compositor-view.hpp> 33 | #include <wayfire/core.hpp> 34 | #include <wayfire/debug.hpp> 35 | #include <wayfire/gtk-shell.hpp> 36 | #include <wayfire/option-wrapper.hpp> 37 | #include <wayfire/output-layout.hpp> 38 | #include <wayfire/output.hpp> 39 | #include <wayfire/plugin.hpp> 40 | #include <wayfire/plugins/common/view-change-viewport-signal.hpp> 41 | #include <wayfire/render-manager.hpp> 42 | #include <wayfire/signal-definitions.hpp> 43 | #include <wayfire/util.hpp> 44 | #include <wayfire/util/duration.hpp> 45 | #include <wayfire/util/log.hpp> 46 | #include <wayfire/view.hpp> 47 | #include <wayfire/workspace-manager.hpp> 48 | 49 | wf::option_wrapper_t<bool> xwayland_enabled("core/xwayland"); 50 | 51 | wf::compositor_core_t& core = wf::get_core(); 52 | std::vector<wf::output_t*> wf_outputs = core.output_layout->get_outputs(); 53 | std::set<wf::output_t*> connected_wf_outputs; 54 | GSettings* settings; 55 | std::map<wf::output_t*, std::unique_ptr<wf::plugin_grab_interface_t>> 56 | grab_interfaces; 57 | 58 | uint focused_view_id; 59 | bool find_view_under_action = false; 60 | GDBusNodeInfo* introspection_data = nullptr; 61 | GDBusConnection* dbus_connection; 62 | uint owner_id; 63 | 64 | static gboolean 65 | check_view_toplevel (wayfire_view view) 66 | { 67 | if (!view) { 68 | return FALSE; 69 | } 70 | 71 | if (!view->is_mapped()) { 72 | return FALSE; 73 | } 74 | 75 | if (view->role != wf::VIEW_ROLE_TOPLEVEL) { 76 | return FALSE; 77 | } 78 | 79 | if (!view->get_output()) { 80 | return FALSE; 81 | } 82 | 83 | return TRUE; 84 | } 85 | 86 | static wayfire_view 87 | get_view_from_view_id (uint view_id) 88 | { 89 | std::vector<wayfire_view> view_vector; 90 | wayfire_view view; 91 | 92 | view_vector = core.get_all_views(); 93 | 94 | // there is no view_id 0 use it as get_active_view(hint) 95 | if (view_id == 0) { 96 | view = core.get_cursor_focus_view(); 97 | if (check_view_toplevel(view)) { 98 | return view; 99 | } 100 | } 101 | 102 | for (auto it = view_vector.begin(); it != view_vector.end(); ++it) 103 | { 104 | wayfire_view v = *it; 105 | if (check_view_toplevel(v)) { 106 | if (v->get_id() == view_id) { 107 | return v; 108 | } 109 | } 110 | } 111 | 112 | return view; 113 | } 114 | 115 | static wf::output_t* 116 | get_output_from_output_id (uint output_id) 117 | { 118 | for (wf::output_t* wf_output : wf_outputs) 119 | { 120 | if (wf_output->get_id() == output_id) { 121 | return wf_output; 122 | } 123 | } 124 | 125 | return nullptr; 126 | } 127 | 128 | static void 129 | restack_view (uint view_id, uint related_view_id, gboolean above) 130 | { 131 | if (view_id == related_view_id) { 132 | return; 133 | } 134 | 135 | wf::wl_idle_call* idle_call = new wf::wl_idle_call; 136 | idle_call->run_once([=] () 137 | { 138 | wayfire_view view = get_view_from_view_id(view_id); 139 | wayfire_view related_view = get_view_from_view_id(related_view_id); 140 | 141 | if (!check_view_toplevel(view) || !check_view_toplevel(related_view)) { 142 | delete idle_call; 143 | 144 | return; 145 | } 146 | 147 | wf::output_t* output = view->get_output(); 148 | if (!output) { 149 | delete idle_call; 150 | 151 | return; 152 | } 153 | 154 | if (above) { 155 | view->get_output()->workspace->restack_above(view, related_view); 156 | } 157 | else 158 | { 159 | view->get_output()->workspace->restack_below(view, related_view); 160 | } 161 | 162 | delete idle_call; 163 | }); 164 | } 165 | 166 | /* 167 | * It is a deliberate design choice to have 168 | * methods / signals instead of properties 169 | * 170 | * Not all clients fully support 171 | * automatic property change notifcations! 172 | */ 173 | const gchar introspection_xml [] = 174 | "<node>" 175 | " <interface name='org.wayland.compositor'>" 176 | // "<property type='au' name='view_vector_ids' access='read'/>" 177 | // kept as example 178 | /************************* Methods ************************/ 179 | // Draft methods 180 | // " <method name='inhibit_output_start'/>" 181 | // " <method name='inhibit_output_stop'/>" 182 | 183 | // " <method name='trigger_show_desktop'/>" 184 | // " <method name='trigger_show_overview'/>" 185 | 186 | " <method name='query_cursor_position'>" 187 | " <arg type='d' name='x_pos' direction='out'/>" 188 | " <arg type='d' name='y_pos' direction='out'/>" 189 | " </method>" 190 | " <method name='enable_property_mode'>" 191 | " <arg type='b' name='enable' direction='in'/>" 192 | " </method>" 193 | 194 | /************************* Output Methods ************************/ 195 | " <method name='query_output_ids'>" 196 | " <arg direction='out' type='au' />" 197 | " </method>" 198 | " <method name='query_active_output'>" 199 | " <arg type='u' name='output_id' direction='out'/>" 200 | " </method>" 201 | " <method name='query_output_name'>" 202 | " <arg type='u' name='output_id' direction='in'/>" 203 | " <arg type='s' name='name' direction='out'/>" 204 | " </method>" 205 | " <method name='query_output_manufacturer'>" 206 | " <arg type='u' name='output_id' direction='in'/>" 207 | " <arg type='s' name='name' direction='out'/>" 208 | " </method>" 209 | " <method name='query_output_model'>" 210 | " <arg type='u' name='output_id' direction='in'/>" 211 | " <arg type='s' name='name' direction='out'/>" 212 | " </method>" 213 | " <method name='query_output_serial'>" 214 | " <arg type='u' name='output_id' direction='in'/>" 215 | " <arg type='s' name='name' direction='out'/>" 216 | " </method>" 217 | " <method name='query_output_workspace'>" 218 | " <arg type='u' name='output_id' direction='in'/>" 219 | " <arg type='u' name='xHorizontal' direction='out'/>" 220 | " <arg type='u' name='yVertical' direction='out'/>" 221 | " </method>" 222 | " <method name='query_xwayland_display'>" 223 | " <arg type='s' name='xdisplay' direction='out'/>" 224 | " </method>" 225 | /************************* View Methods ************************/ 226 | " <method name='query_view_vector_ids'>" 227 | " <arg direction='out' type='au' />" 228 | " </method>" 229 | " <method name='query_view_vector_taskman_ids'>" 230 | " <arg direction='out' type='au' />" 231 | " </method>" 232 | " <method name='query_view_app_id'>" 233 | " <arg type='u' name='view_id' direction='in'/>" 234 | " <arg type='s' name='app_id' direction='out'/>" 235 | " </method>" 236 | " <method name='query_view_app_id_gtk_shell'>" 237 | " <arg type='u' name='view_id' direction='in'/>" 238 | " <arg type='s' name='app_id' direction='out'/>" 239 | " </method>" 240 | " <method name='query_view_app_id_xwayland_net_wm_name'>" 241 | " <arg type='u' name='view_id' direction='in'/>" 242 | " <arg type='s' name='app_id' direction='out'/>" 243 | " </method>" 244 | " <method name='query_view_title'>" 245 | " <arg type='u' name='view_id' direction='in'/>" 246 | " <arg type='s' name='title' direction='out'/>" 247 | " </method>" 248 | " <method name='query_view_credentials'>" 249 | " <arg type='u' name='view_id' direction='in'/>" 250 | " <arg type='i' name='pid' direction='out'/>" 251 | " <arg type='u' name='uid' direction='out'/>" 252 | " <arg type='u' name='gid' direction='out'/>" 253 | " </method>" 254 | " <method name='query_view_active'>" 255 | " <arg type='u' name='view_id' direction='in'/>" 256 | " <arg type='b' name='view_state' direction='out'/>" 257 | " </method>" 258 | " <method name='query_view_minimized'>" 259 | " <arg type='u' name='view_id' direction='in'/>" 260 | " <arg type='b' name='view_state' direction='out'/>" 261 | " </method>" 262 | " <method name='query_view_maximized'>" 263 | " <arg type='u' name='view_id' direction='in'/>" 264 | " <arg type='b' name='view_state' direction='out'/>" 265 | " </method>" 266 | " <method name='query_view_fullscreen'>" 267 | " <arg type='u' name='view_id' direction='in'/>" 268 | " <arg type='b' name='view_state' direction='out'/>" 269 | " </method>" 270 | " <method name='query_view_output'>" 271 | " <arg type='u' name='view_id' direction='in'/>" 272 | " <arg type='u' name='output' direction='out'/>" 273 | " </method>" 274 | " <method name='query_view_above'>" 275 | " <arg type='u' name='view_id' direction='in'/>" 276 | " <arg type='b' name='above' direction='out'/>" 277 | " </method>" 278 | " <method name='query_view_workspaces'>" 279 | " <arg type='u' name='view_id' direction='in'/>" 280 | " <arg type='a(ii)' name='workspaces' direction='out'/>" 281 | " </method>" 282 | " <method name='query_view_group_leader'>" 283 | " <arg type='u' name='view_id' direction='in'/>" 284 | " <arg type='u' name='view_group_leader_view_id' direction='out'/>" 285 | " </method>" 286 | " <method name='query_view_role'>" 287 | " <arg type='u' name='view_id' direction='in'/>" 288 | " <arg type='u' name='view_state' direction='out'/>" 289 | " </method>" 290 | " <method name='query_workspace_grid_size'>" 291 | " <arg type='i' name='rows' direction='out'/>" 292 | " <arg type='i' name='columns' direction='out'/>" 293 | " </method>" 294 | " <method name='query_view_attention'>" 295 | " <arg type='u' name='view_id' direction='in'/>" 296 | " <arg type='b' name='attention' direction='out'/>" 297 | " </method>" 298 | " <method name='query_view_xwayland_wid'>" 299 | " <arg type='u' name='view_id' direction='in'/>" 300 | " <arg type='u' name='xwayland_wid' direction='out'/>" 301 | " </method>" 302 | " <method name='query_view_xwayland_atom_cardinal'>" 303 | " <arg type='u' name='view_id' direction='in'/>" 304 | " <arg type='s' name='atom' direction='in'/>" 305 | " <arg type='u' name='atom_value' direction='out'/>" 306 | " </method>" 307 | " <method name='query_view_xwayland_atom_string'>" 308 | " <arg type='u' name='view_id' direction='in'/>" 309 | " <arg type='s' name='atom' direction='in'/>" 310 | " <arg type='s' name='atom_value' direction='out'/>" 311 | " </method>" 312 | " <method name='query_view_test_data'>" 313 | " <arg type='u' name='view_id' direction='in'/>" 314 | " <arg type='u' name='value' direction='out'/>" 315 | " <arg type='u' name='value2' direction='out'/>" 316 | " </method>" 317 | " <method name='query_view_below_view'>" 318 | " <arg type='u' name='view_id' direction='in'/>" 319 | " <arg type='i' name='below_view_id' direction='out'/>" 320 | " </method>" 321 | " <method name='query_view_above_view'>" 322 | " <arg type='u' name='view_id' direction='in'/>" 323 | " <arg type='i' name='above_view_id' direction='out'/>" 324 | " </method>" 325 | " <method name='minimize_view'>" 326 | " <arg type='u' name='view_id' direction='in'/>" 327 | " <arg type='u' name='action' direction='in'/>" 328 | " </method>" 329 | " <method name='maximize_view'>" 330 | " <arg type='u' name='view_id' direction='in'/>" 331 | " <arg type='u' name='action' direction='in'/>" 332 | " </method>" 333 | " <method name='focus_view'>" 334 | " <arg type='u' name='view_id' direction='in'/>" 335 | " <arg type='u' name='action' direction='in'/>" 336 | " </method>" 337 | " <method name='fullscreen_view'>" 338 | " <arg type='u' name='view_id' direction='in'/>" 339 | " <arg type='u' name='action' direction='in'/>" 340 | " </method>" 341 | " <method name='close_view'>" 342 | " <arg type='u' name='view_id' direction='in'/>" 343 | " </method>" 344 | " <method name='change_view_minimize_hint'>" 345 | " <arg type='u' name='view_id' direction='in'/>" 346 | " <arg type='i' name='a' direction='in'/>" 347 | " <arg type='i' name='b' direction='in'/>" 348 | " <arg type='i' name='c' direction='in'/>" 349 | " <arg type='i' name='d' direction='in'/>" 350 | " </method>" 351 | " <method name='change_output_view'>" 352 | " <arg type='u' name='view_id' direction='in'/>" 353 | " <arg type='u' name='output' direction='in'/>" 354 | " </method>" 355 | " <method name='change_workspace_view'>" 356 | " <arg type='u' name='view_id' direction='in'/>" 357 | " <arg type='i' name='workspace_horizontal' direction='in'/>" 358 | " <arg type='i' name='workspace_vertical' direction='in'/>" 359 | " </method>" 360 | " <method name='change_workspace_output'>" 361 | " <arg type='u' name='output' direction='in'/>" 362 | " <arg type='i' name='workspace_horizontal' direction='in'/>" 363 | " <arg type='i' name='workspace_vertical' direction='in'/>" 364 | " </method>" 365 | " <method name='change_workspace_all_outputs'>" 366 | " <arg type='i' name='workspace_horizontal' direction='in'/>" 367 | " <arg type='i' name='workspace_vertical' direction='in'/>" 368 | " </method>" 369 | " <method name='change_view_above'>" 370 | " <arg type='u' name='view_id' direction='in'/>" 371 | " <arg type='u' name='action' direction='in'/>" 372 | " </method>" 373 | " <method name='shade_view'>" 374 | " <arg type='u' name='view_id' direction='in'/>" 375 | " <arg type='d' name='value' direction='in'/>" 376 | " </method>" 377 | " <method name='bring_view_to_front'>" 378 | " <arg type='u' name='view_id' direction='in'/>" 379 | " </method>" 380 | " <method name='restack_view_above'>" 381 | " <arg type='u' name='view_id' direction='in'/>" 382 | " <arg type='u' name='view_id_now_above_view_id' direction='in'/>" 383 | " </method>" 384 | " <method name='restack_view_below'>" 385 | " <arg type='u' name='view_id' direction='in'/>" 386 | " <arg type='u' name='view_id_now_below_view_id' direction='in'/>" 387 | " </method>" 388 | " <method name='update_view_minimize_hint'>" 389 | " <arg type='u' name='view_id' direction='in'/>" 390 | " </method>" 391 | " <method name='show_desktop'>" 392 | " <arg type='b' name='show' direction='in'/>" 393 | " </method>" 394 | " <method name='scale'>" 395 | " <arg type='b' name='all_workspaces' direction='in'/>" 396 | " <arg type='s' name='app_id_filter' direction='in'/>" 397 | " </method>" 398 | " <method name='ensure_view_visible'>" 399 | " <arg type='u' name='view_id' direction='in'/>" 400 | " </method>" 401 | /************************* Signals ************************/ 402 | /*** 403 | * Core Input Signals 404 | ***/ 405 | " <signal name='pointer_clicked'>" 406 | " <arg type='d' name='x_pos'/>" 407 | " <arg type='d' name='y_pos'/>" 408 | " <arg type='u' name='button'/>" 409 | " <arg type='b' name='button_released'/>" 410 | " </signal>" 411 | " <signal name='tablet_touched'/>" 412 | 413 | /*** 414 | * View related signals, emitted from various 415 | * sources 416 | ***/ 417 | " <signal name='view_added'>" 418 | " <arg type='u' name='view_id'/>" 419 | " </signal>" 420 | " <signal name='view_closed'>" 421 | " <arg type='u' name='view_id'/>" 422 | " </signal>" 423 | " <signal name='view_app_id_changed'>" 424 | " <arg type='u' name='view_id'/>" 425 | " <arg type='s' name='new_app_id'/>" 426 | " </signal>" 427 | " <signal name='view_title_changed'>" 428 | " <arg type='u' name='view_id'/>" 429 | " <arg type='s' name='new_title'/>" 430 | " </signal>" 431 | " <signal name='view_output_move_requested'>" 432 | " <arg type='u' name='view_id'/>" 433 | " <arg type='u' name='old_output'/>" 434 | " <arg type='u' name='new_output'/>" 435 | " </signal>" 436 | " <signal name='view_output_moved'>" 437 | " <arg type='u' name='view_id'/>" 438 | " <arg type='u' name='old_output'/>" 439 | " <arg type='u' name='new_output'/>" 440 | " </signal>" 441 | " <signal name='view_workspaces_changed'>" 442 | " <arg type='u' name='view_id'/>" 443 | " </signal>" 444 | " <signal name='view_attention_changed'>" 445 | " <arg type='u' name='view_id'/>" 446 | " <arg type='b' name='attention'/>" 447 | " </signal>" 448 | " <signal name='view_group_leader_changed'>" 449 | " <arg type='u' name='view_id'/>" 450 | " <arg type='u' name='view_group_leader_view_id'/>" 451 | " </signal>" 452 | " <signal name='view_tiling_changed'>" 453 | " <arg type='u' name='view_id'/>" 454 | " <arg type='u' name='edges'/>" 455 | " </signal>" 456 | " <signal name='view_geometry_changed'>" 457 | " <arg type='u' name='view_id'/>" 458 | " <arg type='i' name='x'/>" 459 | " <arg type='i' name='y'/>" 460 | " <arg type='i' name='width'/>" 461 | " <arg type='i' name='height'/>" 462 | " </signal>" 463 | " <signal name='view_moving_changed'>" 464 | " <arg type='u' name='view_id'/>" 465 | " </signal>" 466 | " <signal name='view_resizing_changed'>" 467 | " <arg type='u' name='view_id'/>" 468 | " </signal>" 469 | " <signal name='view_role_changed'>" 470 | " <arg type='u' name='view_id'/>" 471 | " <arg type='u' name='view_role'/>" 472 | " </signal>" 473 | " <signal name='view_maximized_changed'>" 474 | " <arg type='u' name='view_id'/>" 475 | " <arg type='b' name='maximized'/>" 476 | " </signal>" 477 | " <signal name='view_minimized_changed'>" 478 | " <arg type='u' name='view_id'/>" 479 | " <arg type='b' name='minimized'/>" 480 | " </signal>" 481 | " <signal name='view_fullscreen_changed'>" 482 | " <arg type='u' name='view_id'/>" 483 | " <arg type='b' name='fullscreened'/>" 484 | " </signal>" 485 | " <signal name='view_focus_changed'>" 486 | " <arg type='u' name='view_id'/>" 487 | " </signal>" 488 | " <signal name='view_keep_above_changed'>" 489 | " <arg type='u' name='view_id'/>" 490 | " <arg type='b' name='above'/>" 491 | " </signal>" 492 | /*** 493 | * Output related signals, emitted from various 494 | * sources 495 | ***/ 496 | " <signal name='output_workspace_changed'>" 497 | " <arg type='u' name='output_id'/>" 498 | " <arg type='i' name='workspace_horizontal'/>" 499 | " <arg type='i' name='workspace_vertical'/>" 500 | " </signal>" 501 | " <signal name='output_added'>" 502 | " <arg type='u' name='output_id'/>" 503 | " </signal>" 504 | " <signal name='output_removed'>" 505 | " <arg type='u' name='output_id'/>" 506 | " </signal>" 507 | " <signal name='output_configuration_changed'/>" 508 | 509 | /*** 510 | * For wf-prop & co 511 | ***/ 512 | " <signal name='view_pressed'>" 513 | " <arg type='u' name='view_id'/>" 514 | " </signal>" 515 | /*** 516 | * Tentative signals 517 | * " <signal name='hotspot_edge_trigger_stop'>" 518 | * " <arg type='u' name='hotspot_edge'/>" 519 | * " </signal>" 520 | * " <signal name='hotspot_edge_triggered'>" 521 | * " <arg type='i' name='hotspot_edge'/>" 522 | * " </signal>" 523 | * " <signal name='hotspot_edge_trigger_stop'>" 524 | * " <arg type='i' name='hotspot_edge'/>" 525 | * " </signal>" 526 | * 527 | * " <signal name='inhibit_output_started'/>" 528 | * " <signal name='inhibit_output_stopped'/>" 529 | ***/ 530 | 531 | " </interface>" 532 | "</node>"; 533 | 534 | static void 535 | handle_method_call (GDBusConnection* connection, const gchar* sender, 536 | const gchar* object_path, 537 | const gchar* interface_name, 538 | const gchar* method_name, GVariant* parameters, 539 | GDBusMethodInvocation* invocation, 540 | gpointer user_data) 541 | { 542 | #ifdef DBUS_PLUGIN_DEBUG 543 | LOG(wf::log::LOG_LEVEL_DEBUG, "handle_method_call bus called ", method_name); 544 | #endif 545 | 546 | if (g_strcmp0(method_name, "change_view_above") == 0) { 547 | uint view_id; 548 | uint action; 549 | 550 | g_variant_get(parameters, "(uu)", &view_id, &action); 551 | wf::wl_idle_call* idle_call = new wf::wl_idle_call; 552 | idle_call->run_once([=] () 553 | { 554 | wayfire_view view = get_view_from_view_id(view_id); 555 | if (!check_view_toplevel(view)) { 556 | delete idle_call; 557 | 558 | return; 559 | } 560 | 561 | bool is_above; 562 | wf::output_t* output; 563 | wf::_view_signal signal_data; 564 | is_above = view->has_data("wm-actions-above"); 565 | output = view->get_output(); 566 | 567 | if ((action == 0) && is_above) { 568 | signal_data.view = view; 569 | output->emit_signal("wm-actions-toggle-above", &signal_data); 570 | } 571 | else 572 | if ((action == 1) && !is_above) 573 | { 574 | signal_data.view = view; 575 | output->emit_signal("wm-actions-toggle-above", &signal_data); 576 | } 577 | else 578 | if (action == 2) 579 | { 580 | signal_data.view = view; 581 | output->emit_signal("wm-actions-toggle-above", &signal_data); 582 | } 583 | 584 | delete idle_call; 585 | }); 586 | 587 | g_dbus_method_invocation_return_value(invocation, NULL); 588 | 589 | return; 590 | } 591 | 592 | /*************** View Actions ****************/ 593 | else 594 | if (g_strcmp0(method_name, "ensure_view_visible") == 0) 595 | { 596 | uint view_id; 597 | g_variant_get(parameters, "(u)", &view_id); 598 | wf::wl_idle_call* idle_call = new wf::wl_idle_call; 599 | idle_call->run_once([=] () 600 | { 601 | wayfire_view view = get_view_from_view_id(view_id); 602 | 603 | if (check_view_toplevel(view)) { 604 | view->get_output()->ensure_visible(view); 605 | } 606 | 607 | delete idle_call; 608 | }); 609 | g_dbus_method_invocation_return_value(invocation, NULL); 610 | 611 | return; 612 | } 613 | else 614 | if (g_strcmp0(method_name, "update_view_minimize_hint") == 0) 615 | { 616 | uint view_id; 617 | g_variant_get(parameters, "(u)", &view_id); 618 | wf::wl_idle_call* idle_call = new wf::wl_idle_call; 619 | idle_call->run_once([=] () 620 | { 621 | wayfire_view view = get_view_from_view_id(view_id); 622 | 623 | if (check_view_toplevel(view)) { 624 | wf::pointf_t pos; 625 | pos = core.get_active_output()->get_cursor_position(); 626 | view->set_minimize_hint({(int)pos.x, (int)pos.y, 5, 5}); 627 | } 628 | 629 | delete idle_call; 630 | }); 631 | g_dbus_method_invocation_return_value(invocation, NULL); 632 | 633 | return; 634 | } 635 | else 636 | if (g_strcmp0(method_name, "shade_view") == 0) 637 | { 638 | uint view_id; 639 | double intensity; 640 | 641 | g_variant_get(parameters, "(ud)", &view_id, &intensity); 642 | 643 | wf::wl_idle_call* idle_call = new wf::wl_idle_call; 644 | idle_call->run_once([=] () 645 | { 646 | wayfire_view view = get_view_from_view_id(view_id); 647 | if (!check_view_toplevel(view)) { 648 | delete idle_call; 649 | 650 | return; 651 | } 652 | 653 | if (intensity == 1.0) { 654 | if (view->get_transformer("dbus-shade")) { 655 | view->pop_transformer("dbus-shade"); 656 | } 657 | } 658 | else 659 | { 660 | wf::view_2D* transformer; 661 | if (!view->get_transformer("dbus-shade")) { 662 | view->add_transformer(std::make_unique<wf::view_2D> (view), 663 | "dbus-shade"); 664 | } 665 | 666 | transformer = dynamic_cast<wf::view_2D*> ( 667 | view->get_transformer("dbus-shade").get()); 668 | 669 | if (transformer->alpha != (float)intensity) { 670 | transformer->alpha = (float)intensity; 671 | // view->damage(); 672 | } 673 | } 674 | 675 | delete idle_call; 676 | }); 677 | g_dbus_method_invocation_return_value(invocation, NULL); 678 | 679 | return; 680 | } 681 | else 682 | if (g_strcmp0(method_name, "bring_view_to_front") == 0) 683 | { 684 | uint view_id; 685 | g_variant_get(parameters, "(u)", &view_id); 686 | 687 | wf::wl_idle_call* idle_call = new wf::wl_idle_call; 688 | idle_call->run_once([=] () 689 | { 690 | wayfire_view view = get_view_from_view_id(view_id); 691 | 692 | if (check_view_toplevel(view)) { 693 | wf::output_t* output = view->get_output(); 694 | output->workspace->bring_to_front(view); 695 | } 696 | 697 | delete idle_call; 698 | }); 699 | 700 | g_dbus_method_invocation_return_value(invocation, NULL); 701 | 702 | return; 703 | } 704 | else 705 | if (g_strcmp0(method_name, "restack_view_above") == 0) 706 | { 707 | uint view_id; 708 | uint related_view_id; 709 | g_variant_get(parameters, "(uu)", &view_id, &related_view_id); 710 | restack_view(view_id, related_view_id, TRUE); 711 | g_dbus_method_invocation_return_value(invocation, NULL); 712 | 713 | return; 714 | } 715 | else 716 | if (g_strcmp0(method_name, "restack_view_below") == 0) 717 | { 718 | uint view_id; 719 | uint related_view_id; 720 | g_variant_get(parameters, "(uu)", &view_id, &related_view_id); 721 | restack_view(view_id, related_view_id, FALSE); 722 | g_dbus_method_invocation_return_value(invocation, NULL); 723 | 724 | return; 725 | } 726 | else 727 | if (g_strcmp0(method_name, "minimize_view") == 0) 728 | { 729 | uint view_id; 730 | uint action; 731 | 732 | g_variant_get(parameters, "(uu)", &view_id, &action); 733 | 734 | wf::wl_idle_call* idle_call = new wf::wl_idle_call; 735 | idle_call->run_once([=] () 736 | { 737 | wayfire_view view = get_view_from_view_id(view_id); 738 | if (!check_view_toplevel(view)) { 739 | delete idle_call; 740 | 741 | return; 742 | } 743 | 744 | if ((action == 0) && view->minimized) { 745 | view->minimize_request(false); 746 | } 747 | 748 | else 749 | if ((action == 1) && !view->minimized) 750 | { 751 | view->minimize_request(true); 752 | } 753 | 754 | else 755 | if (action == 2) 756 | { 757 | view->minimize_request(!view->minimized); 758 | } 759 | 760 | delete idle_call; 761 | }); 762 | 763 | g_dbus_method_invocation_return_value(invocation, NULL); 764 | 765 | return; 766 | } 767 | else 768 | if (g_strcmp0(method_name, "maximize_view") == 0) 769 | { 770 | uint view_id; 771 | uint action; 772 | g_variant_get(parameters, "(uu)", &view_id, &action); 773 | 774 | wf::wl_idle_call* idle_call = new wf::wl_idle_call; 775 | idle_call->run_once([=] () 776 | { 777 | wayfire_view view = get_view_from_view_id(view_id); 778 | if (!check_view_toplevel(view)) { 779 | delete idle_call; 780 | 781 | return; 782 | } 783 | 784 | if (action == 0) { 785 | view->tile_request(0); 786 | } 787 | 788 | else 789 | if (action == 1) 790 | { 791 | view->tile_request(wf::TILED_EDGES_ALL); 792 | } 793 | 794 | else 795 | if (action == 2) 796 | { 797 | if (view->tiled_edges == wf::TILED_EDGES_ALL) { 798 | view->tile_request(0); 799 | } 800 | else 801 | { 802 | view->tile_request(wf::TILED_EDGES_ALL); 803 | } 804 | } 805 | 806 | delete idle_call; 807 | }); 808 | g_dbus_method_invocation_return_value(invocation, NULL); 809 | 810 | return; 811 | } 812 | else 813 | if (g_strcmp0(method_name, "focus_view") == 0) 814 | { 815 | uint view_id; 816 | uint action; 817 | g_variant_get(parameters, "(uu)", &view_id, &action); 818 | 819 | wf::wl_idle_call* idle_call = new wf::wl_idle_call; 820 | idle_call->run_once([=] () 821 | { 822 | wayfire_view view = get_view_from_view_id(view_id); 823 | if (!check_view_toplevel(view)) { 824 | delete idle_call; 825 | 826 | return; 827 | } 828 | 829 | if (action == 0) { 830 | view->set_activated(false); 831 | } 832 | 833 | else 834 | if (action == 1) 835 | { 836 | view->set_activated(true); 837 | view->focus_request(); 838 | } 839 | 840 | delete idle_call; 841 | }); 842 | g_dbus_method_invocation_return_value(invocation, NULL); 843 | 844 | return; 845 | } 846 | else 847 | if (g_strcmp0(method_name, "fullscreen_view") == 0) 848 | { 849 | uint view_id; 850 | uint action; 851 | g_variant_get(parameters, "(uu)", &view_id, &action); 852 | 853 | wf::wl_idle_call* idle_call = new wf::wl_idle_call; 854 | idle_call->run_once([=] () 855 | { 856 | wayfire_view view = get_view_from_view_id(view_id); 857 | if (!check_view_toplevel(view)) { 858 | delete idle_call; 859 | 860 | return; 861 | } 862 | 863 | wf::output_t* output = core.get_active_output(); 864 | 865 | if (action == 0) { 866 | view->fullscreen_request(output, false); 867 | } 868 | 869 | else 870 | if (action == 1) 871 | { 872 | view->fullscreen_request(output, true); 873 | } 874 | 875 | else 876 | if (action == 2) 877 | { 878 | view->fullscreen_request(output, !view->fullscreen); 879 | } 880 | 881 | delete idle_call; 882 | }); 883 | g_dbus_method_invocation_return_value(invocation, NULL); 884 | 885 | return; 886 | } 887 | else 888 | if (g_strcmp0(method_name, "close_view") == 0) 889 | { 890 | uint view_id; 891 | g_variant_get(parameters, "(u)", &view_id); 892 | 893 | wf::wl_idle_call* idle_call = new wf::wl_idle_call; 894 | idle_call->run_once([=] () 895 | { 896 | wayfire_view view = get_view_from_view_id(view_id); 897 | 898 | if (check_view_toplevel(view)) { 899 | view->close(); 900 | } 901 | 902 | delete idle_call; 903 | }); 904 | g_dbus_method_invocation_return_value(invocation, NULL); 905 | 906 | return; 907 | } 908 | else 909 | if (g_strcmp0(method_name, "change_view_minimize_hint") == 0) 910 | { 911 | uint view_id; 912 | int x, y, width, height; 913 | 914 | g_variant_get(parameters, "(uiiii)", &view_id, &x, &y, &width, &height); 915 | 916 | wf::wl_idle_call* idle_call = new wf::wl_idle_call; 917 | idle_call->run_once([=] () 918 | { 919 | wayfire_view view = get_view_from_view_id(view_id); 920 | if (!check_view_toplevel(view)) { 921 | delete idle_call; 922 | 923 | return; 924 | } 925 | 926 | view->set_minimize_hint({x, y, width, height}); 927 | delete idle_call; 928 | }); 929 | 930 | g_dbus_method_invocation_return_value(invocation, nullptr); 931 | 932 | return; 933 | } 934 | 935 | else 936 | if (g_strcmp0(method_name, "change_output_view") == 0) 937 | { 938 | uint view_id; 939 | uint output_id; 940 | 941 | g_variant_get(parameters, "(uu)", &view_id, &output_id); 942 | 943 | wf::wl_idle_call* idle_call = new wf::wl_idle_call; 944 | idle_call->run_once([=] () 945 | { 946 | wayfire_view view = get_view_from_view_id(view_id); 947 | if (!check_view_toplevel(view)) { 948 | delete idle_call; 949 | 950 | return; 951 | } 952 | 953 | wf::output_t* output = get_output_from_output_id(output_id); 954 | if (output) { 955 | core.move_view_to_output(view, output, TRUE); 956 | } 957 | 958 | delete idle_call; 959 | }); 960 | g_dbus_method_invocation_return_value(invocation, NULL); 961 | 962 | return; 963 | } 964 | else 965 | if (g_strcmp0(method_name, "change_workspace_view") == 0) 966 | { 967 | uint view_id; 968 | int new_workspace_x; 969 | int new_workspace_y; 970 | 971 | g_variant_get(parameters, "(uii)", &view_id, &new_workspace_x, 972 | &new_workspace_y); 973 | 974 | wf::wl_idle_call* idle_call = new wf::wl_idle_call; 975 | idle_call->run_once([=] () 976 | { 977 | wayfire_view view = get_view_from_view_id(view_id); 978 | if (!check_view_toplevel(view)) { 979 | delete idle_call; 980 | 981 | return; 982 | } 983 | 984 | wf::point_t new_workspace_coord = {new_workspace_x, new_workspace_y}; 985 | wf::output_t* output = view->get_output(); 986 | output->workspace->move_to_workspace(view, new_workspace_coord); 987 | delete idle_call; 988 | }); 989 | 990 | g_dbus_method_invocation_return_value(invocation, NULL); 991 | 992 | return; 993 | } 994 | else 995 | if (g_strcmp0(method_name, "change_workspace_output") == 0) 996 | { 997 | uint output_id; 998 | int new_workspace_x; 999 | int new_workspace_y; 1000 | 1001 | g_variant_get(parameters, "(uii)", &output_id, &new_workspace_x, 1002 | &new_workspace_y); 1003 | 1004 | wf::wl_idle_call* idle_call = new wf::wl_idle_call; 1005 | idle_call->run_once([=] () 1006 | { 1007 | wf::output_t* output = get_output_from_output_id(output_id); 1008 | 1009 | if (output) { 1010 | wf::point_t new_workspace_coord; 1011 | new_workspace_coord = {new_workspace_x, new_workspace_y}; 1012 | output->workspace->request_workspace(new_workspace_coord); 1013 | // Provides animation if available 1014 | } 1015 | 1016 | delete idle_call; 1017 | }); 1018 | g_dbus_method_invocation_return_value(invocation, NULL); 1019 | 1020 | return; 1021 | } 1022 | else 1023 | if (g_strcmp0(method_name, "change_workspace_all_outputs") == 0) 1024 | { 1025 | int new_workspace_x; 1026 | int new_workspace_y; 1027 | 1028 | g_variant_get(parameters, "(ii)", &new_workspace_x, &new_workspace_y); 1029 | 1030 | wf::wl_idle_call* idle_call = new wf::wl_idle_call; 1031 | idle_call->run_once([=] () 1032 | { 1033 | wf::point_t new_workspace_coord; 1034 | new_workspace_coord = {new_workspace_x, new_workspace_y}; 1035 | 1036 | for (wf::output_t* output : wf_outputs) 1037 | { 1038 | if (output) { 1039 | output->workspace->request_workspace(new_workspace_coord); 1040 | } 1041 | } 1042 | 1043 | delete idle_call; 1044 | }); 1045 | g_dbus_method_invocation_return_value(invocation, NULL); 1046 | 1047 | return; 1048 | } 1049 | else 1050 | if (g_strcmp0(method_name, "show_desktop") == 0) 1051 | { 1052 | // g_variant_ref(parameters); 1053 | // wl_event_loop_add_idle(core.ev_loop, 1054 | // local_thread_show_desktop, 1055 | // static_cast<void*> (parameters)); 1056 | g_dbus_method_invocation_return_value(invocation, NULL); 1057 | 1058 | return; 1059 | } 1060 | else 1061 | if (g_strcmp0(method_name, "scale") == 0) 1062 | { 1063 | gboolean all_workspaces = FALSE; 1064 | gchar* app_id = nullptr; 1065 | g_variant_get(parameters, "(bs)", &all_workspaces, &app_id); 1066 | 1067 | wf::wl_idle_call* idle_call = new wf::wl_idle_call; 1068 | idle_call->run_once( 1069 | [all_workspaces, app_id = std::string(app_id), idle_call] () 1070 | { 1071 | wf::output_t* output = core.get_active_output(); 1072 | auto filter = dbus_scale_filter::get(output); 1073 | filter->set_filter(std::move(app_id)); 1074 | 1075 | if (output->is_plugin_active("scale")) { 1076 | output->emit_signal("scale-update", nullptr); 1077 | } 1078 | else 1079 | { 1080 | wf::activator_data_t adata; 1081 | adata.source = wf::activator_source_t::PLUGIN; 1082 | output->call_plugin( 1083 | all_workspaces ? "scale/toggle_all" : "scale/toggle", adata); 1084 | } 1085 | 1086 | delete idle_call; 1087 | }); 1088 | 1089 | g_dbus_method_invocation_return_value(invocation, nullptr); 1090 | } 1091 | 1092 | /*************** Non-reffing actions at end ****************/ 1093 | else 1094 | if (g_strcmp0(method_name, "enable_property_mode") == 0) 1095 | { 1096 | bool enable; 1097 | g_variant_get(parameters, "(b)", &enable); 1098 | find_view_under_action = enable; 1099 | 1100 | /** 1101 | * Eventually store current cursor 1102 | * and restore it if different from 1103 | * "default" 1104 | */ 1105 | if (enable) { 1106 | for (wf::output_t* output : wf_outputs) 1107 | { 1108 | if (!output->activate_plugin(grab_interfaces[output])) { 1109 | continue; 1110 | } 1111 | 1112 | grab_interfaces[output]->grab(); 1113 | } 1114 | 1115 | wf::wl_idle_call* idle_call = new wf::wl_idle_call; 1116 | idle_call->run_once([core, idle_call] () 1117 | { 1118 | core.set_cursor("crosshair"); 1119 | delete idle_call; 1120 | }); 1121 | } 1122 | else 1123 | { 1124 | for (wf::output_t* output : wf_outputs) 1125 | { 1126 | output->deactivate_plugin(grab_interfaces[output]); 1127 | grab_interfaces[output]->ungrab(); 1128 | } 1129 | 1130 | wf::wl_idle_call* idle_call = new wf::wl_idle_call; 1131 | idle_call->run_once([=] () 1132 | { 1133 | core.set_cursor("default"); 1134 | delete idle_call; 1135 | }); 1136 | } 1137 | 1138 | g_dbus_method_invocation_return_value(invocation, nullptr); 1139 | 1140 | return; 1141 | } 1142 | else 1143 | if (g_strcmp0(method_name, "query_cursor_position") == 0) 1144 | { 1145 | /* 1146 | * It uses the output relative cursor position 1147 | * as expected by minimize rect and popup positions 1148 | */ 1149 | wf::pointf_t cursor_position; 1150 | GVariant* value; 1151 | 1152 | cursor_position = core.get_active_output()->get_cursor_position(); 1153 | value = g_variant_new("(dd)", cursor_position.x, cursor_position.y); 1154 | g_dbus_method_invocation_return_value(invocation, value); 1155 | 1156 | return; 1157 | } 1158 | else 1159 | if (g_strcmp0(method_name, "query_output_ids") == 0) 1160 | { 1161 | GVariantBuilder builder; 1162 | GVariant* value; 1163 | 1164 | g_variant_builder_init(&builder, G_VARIANT_TYPE("au")); 1165 | 1166 | for (wf::output_t* wf_output : wf_outputs) 1167 | { 1168 | g_variant_builder_add(&builder, "u", wf_output->get_id()); 1169 | } 1170 | 1171 | value = g_variant_new("(au)", &builder); 1172 | g_dbus_method_invocation_return_value(invocation, value); 1173 | 1174 | return; 1175 | } 1176 | else 1177 | if (g_strcmp0(method_name, "query_active_output") == 0) 1178 | { 1179 | uint output_id; 1180 | output_id = core.get_active_output()->get_id(); 1181 | g_dbus_method_invocation_return_value(invocation, 1182 | g_variant_new("(u)", output_id)); 1183 | 1184 | return; 1185 | } 1186 | else 1187 | if (g_strcmp0(method_name, "query_view_vector_ids") == 0) 1188 | { 1189 | std::vector<nonstd::observer_ptr<wf::view_interface_t>> view_vector; 1190 | GVariantBuilder builder; 1191 | GVariant* value; 1192 | 1193 | view_vector = core.get_all_views(); 1194 | g_variant_builder_init(&builder, G_VARIANT_TYPE("au")); 1195 | for (auto it = begin(view_vector); it != end(view_vector); ++it) 1196 | { 1197 | g_variant_builder_add(&builder, "u", it->get()->get_id()); 1198 | } 1199 | 1200 | value = g_variant_new("(au)", &builder); 1201 | g_dbus_method_invocation_return_value(invocation, value); 1202 | 1203 | return; 1204 | } 1205 | else 1206 | if (g_strcmp0(method_name, "query_view_vector_taskman_ids") == 0) 1207 | { 1208 | std::vector<nonstd::observer_ptr<wf::view_interface_t>> view_vector = 1209 | core.get_all_views(); 1210 | GVariantBuilder builder; 1211 | GVariant* value; 1212 | 1213 | g_variant_builder_init(&builder, G_VARIANT_TYPE("au")); 1214 | for (auto it = begin(view_vector); it != end(view_vector); ++it) 1215 | { 1216 | if ((it->get()->role != wf::VIEW_ROLE_TOPLEVEL) || 1217 | !it->get()->is_mapped()) { 1218 | continue; 1219 | } 1220 | else 1221 | { 1222 | g_variant_builder_add(&builder, "u", it->get()->get_id()); 1223 | } 1224 | } 1225 | 1226 | value = g_variant_new("(au)", &builder); 1227 | g_dbus_method_invocation_return_value(invocation, value); 1228 | 1229 | return; 1230 | } 1231 | /*************** Output Properties ****************/ 1232 | else 1233 | if (g_strcmp0(method_name, "query_output_name") == 0) 1234 | { 1235 | uint output_id; 1236 | gchar* response = "nullptr"; 1237 | g_variant_get(parameters, "(u)", &output_id); 1238 | wf::output_t* wf_output = get_output_from_output_id(output_id); 1239 | 1240 | if (wf_output != nullptr) { 1241 | response = g_strdup_printf(wf_output->to_string().c_str()); 1242 | } 1243 | 1244 | g_dbus_method_invocation_return_value(invocation, 1245 | g_variant_new("(s)", response)); 1246 | if (wf_output != nullptr) { 1247 | g_free(response); 1248 | } 1249 | 1250 | return; 1251 | } 1252 | else 1253 | if (g_strcmp0(method_name, "query_output_manufacturer") == 0) 1254 | { 1255 | uint output_id; 1256 | gchar* response = "nullptr"; 1257 | wf::output_t* output; 1258 | wlr_output* wlr_output = nullptr; 1259 | 1260 | g_variant_get(parameters, "(u)", &output_id); 1261 | output = get_output_from_output_id(output_id); 1262 | if (output) { 1263 | wlr_output = output->handle; 1264 | 1265 | if (wlr_output != nullptr) { 1266 | response = g_strdup_printf(wlr_output->make); 1267 | } 1268 | } 1269 | 1270 | g_dbus_method_invocation_return_value(invocation, 1271 | g_variant_new("(s)", response)); 1272 | if (wlr_output != nullptr) { 1273 | g_free(response); 1274 | } 1275 | 1276 | return; 1277 | } 1278 | else 1279 | if (g_strcmp0(method_name, "query_output_model") == 0) 1280 | { 1281 | uint output_id; 1282 | gchar* response = "nullptr"; 1283 | wf::output_t* output; 1284 | wlr_output* wlr_output = nullptr; 1285 | 1286 | g_variant_get(parameters, "(u)", &output_id); 1287 | output = get_output_from_output_id(output_id); 1288 | if (output) { 1289 | wlr_output = output->handle; 1290 | 1291 | if (wlr_output != nullptr) { 1292 | response = g_strdup_printf(wlr_output->model); 1293 | } 1294 | } 1295 | 1296 | g_dbus_method_invocation_return_value(invocation, 1297 | g_variant_new("(s)", response)); 1298 | if (wlr_output != nullptr) { 1299 | g_free(response); 1300 | } 1301 | 1302 | return; 1303 | } 1304 | else 1305 | if (g_strcmp0(method_name, "query_output_serial") == 0) 1306 | { 1307 | uint output_id; 1308 | gchar* response = "nullptr"; 1309 | wf::output_t* wf_output; 1310 | wlr_output* wlr_output = nullptr; 1311 | 1312 | g_variant_get(parameters, "(u)", &output_id); 1313 | wf_output = get_output_from_output_id(output_id); 1314 | wlr_output = wf_output->handle; 1315 | 1316 | if (wlr_output != nullptr) { 1317 | response = g_strdup_printf(wlr_output->serial); 1318 | } 1319 | 1320 | g_dbus_method_invocation_return_value(invocation, 1321 | g_variant_new("(s)", response)); 1322 | if (wlr_output != nullptr) { 1323 | g_free(response); 1324 | } 1325 | 1326 | return; 1327 | } 1328 | else 1329 | if (g_strcmp0(method_name, "query_output_workspace") == 0) 1330 | { 1331 | uint output_id; 1332 | uint horizontal_workspace = 0; 1333 | uint vertical_workspace = 0; 1334 | wf::output_t* wf_output; 1335 | wf::point_t ws; 1336 | 1337 | g_variant_get(parameters, "(u)", &output_id); 1338 | wf_output = get_output_from_output_id(output_id); 1339 | if (wf_output) { 1340 | ws = wf_output->workspace->get_current_workspace(); 1341 | horizontal_workspace = ws.x; 1342 | vertical_workspace = ws.y; 1343 | } 1344 | 1345 | g_dbus_method_invocation_return_value( 1346 | invocation, 1347 | g_variant_new("(uu)", horizontal_workspace, vertical_workspace)); 1348 | 1349 | return; 1350 | } 1351 | else 1352 | if (g_strcmp0(method_name, "query_workspace_grid_size") == 0) 1353 | { 1354 | wf::dimensions_t workspaces; 1355 | workspaces = core.get_active_output()->workspace->get_workspace_grid_size(); 1356 | 1357 | g_dbus_method_invocation_return_value( 1358 | invocation, g_variant_new("(ii)", workspaces.width, workspaces.height)); 1359 | 1360 | return; 1361 | } 1362 | /*************** View Properties ****************/ 1363 | else 1364 | if (g_strcmp0(method_name, "query_view_above_view") == 0) 1365 | { 1366 | uint view_id; 1367 | g_variant_get(parameters, "(u)", &view_id); 1368 | 1369 | wayfire_view view = get_view_from_view_id(view_id); 1370 | wf::output_t* output; 1371 | int view_above = -1; 1372 | std::vector<wayfire_view> workspace_views; 1373 | 1374 | if (!check_view_toplevel(view)) { 1375 | g_dbus_method_invocation_return_value(invocation, 1376 | g_variant_new("(i)", view_above)); 1377 | 1378 | return; 1379 | } 1380 | 1381 | while (view->parent) 1382 | { 1383 | view = view->parent; 1384 | } 1385 | 1386 | if (!check_view_toplevel(view)) { 1387 | g_dbus_method_invocation_return_value( 1388 | invocation, g_variant_new("(i)", view_above)); 1389 | 1390 | return; 1391 | } 1392 | 1393 | output = view->get_output(); 1394 | if (!output) { 1395 | g_dbus_method_invocation_return_value(invocation, 1396 | g_variant_new("(i)", view_above)); 1397 | 1398 | return; 1399 | } 1400 | 1401 | workspace_views = 1402 | output->workspace->get_views_in_layer(wf::MIDDLE_LAYERS); 1403 | 1404 | for (int i = 0; i < workspace_views.size() - 1; i++) 1405 | { 1406 | wayfire_view v = workspace_views[i]; 1407 | if (!check_view_toplevel(v)) { 1408 | continue; 1409 | } 1410 | 1411 | if (v == view) { 1412 | if (i != 0) { 1413 | if (check_view_toplevel(workspace_views[i - 1])) { 1414 | view_above = workspace_views[i - 1]->get_id(); 1415 | } 1416 | 1417 | break; 1418 | } 1419 | } 1420 | } 1421 | 1422 | g_dbus_method_invocation_return_value(invocation, 1423 | g_variant_new("(i)", view_above)); 1424 | 1425 | return; 1426 | } 1427 | else 1428 | if (g_strcmp0(method_name, "query_view_below_view") == 0) 1429 | { 1430 | uint view_id; 1431 | g_variant_get(parameters, "(u)", &view_id); 1432 | 1433 | wayfire_view view = get_view_from_view_id(view_id); 1434 | wf::output_t* output; 1435 | int view_below = -1; 1436 | std::vector<wayfire_view> workspace_views; 1437 | 1438 | if (!check_view_toplevel(view)) { 1439 | g_dbus_method_invocation_return_value(invocation, 1440 | g_variant_new("(i)", view_below)); 1441 | 1442 | return; 1443 | } 1444 | 1445 | while (view->parent) 1446 | { 1447 | view = view->parent; 1448 | } 1449 | 1450 | if (!check_view_toplevel(view)) { 1451 | g_dbus_method_invocation_return_value( 1452 | invocation, g_variant_new("(i)", view_below)); 1453 | 1454 | return; 1455 | } 1456 | 1457 | output = view->get_output(); 1458 | if (!output) { 1459 | g_dbus_method_invocation_return_value(invocation, 1460 | g_variant_new("(i)", view_below)); 1461 | 1462 | return; 1463 | } 1464 | 1465 | workspace_views = 1466 | output->workspace->get_views_in_layer(wf::MIDDLE_LAYERS); 1467 | 1468 | for (int i = 0; i < workspace_views.size() - 1; i++) 1469 | { 1470 | wayfire_view v = workspace_views[i]; 1471 | if (!check_view_toplevel(v)) { 1472 | continue; 1473 | } 1474 | 1475 | if (v == view) { 1476 | if (i != workspace_views.size() - 1) { 1477 | if (check_view_toplevel(workspace_views[i + 1])) { 1478 | view_below = workspace_views[i + 1]->get_id(); 1479 | } 1480 | 1481 | break; 1482 | } 1483 | } 1484 | 1485 | // if (view_below != -1) 1486 | // { 1487 | // g_warning("Below %s is %s", view->get_title().c_str(), 1488 | // get_view_from_view_id(view_below)->get_title().c_str()); 1489 | // } 1490 | // else 1491 | // { 1492 | // g_warning("No view below %s", view->get_title().c_str()); 1493 | // } 1494 | } 1495 | 1496 | g_dbus_method_invocation_return_value(invocation, 1497 | g_variant_new("(i)", view_below)); 1498 | 1499 | return; 1500 | } 1501 | else 1502 | if (g_strcmp0(method_name, "query_view_app_id") == 0) 1503 | { 1504 | uint view_id; 1505 | gchar* response = "nullptr"; 1506 | wayfire_view view; 1507 | 1508 | g_variant_get(parameters, "(u)", &view_id); 1509 | view = get_view_from_view_id(view_id); 1510 | 1511 | if (!check_view_toplevel(view)) { 1512 | g_dbus_method_invocation_return_value(invocation, 1513 | g_variant_new("(s)", response)); 1514 | 1515 | return; 1516 | } 1517 | 1518 | response = g_strdup(view->get_app_id().c_str()); 1519 | g_dbus_method_invocation_return_value(invocation, 1520 | g_variant_new("(s)", response)); 1521 | g_free(response); 1522 | 1523 | return; 1524 | } 1525 | else 1526 | if (g_strcmp0(method_name, "query_view_app_id_gtk_shell") == 0) 1527 | { 1528 | uint view_id; 1529 | gchar* response = "nullptr"; 1530 | wayfire_view view; 1531 | 1532 | g_variant_get(parameters, "(u)", &view_id); 1533 | view = get_view_from_view_id(view_id); 1534 | 1535 | if (!check_view_toplevel(view)) { 1536 | g_dbus_method_invocation_return_value(invocation, 1537 | g_variant_new("(s)", response)); 1538 | 1539 | return; 1540 | } 1541 | 1542 | response = g_strdup(get_gtk_shell_app_id(view).c_str()); 1543 | g_dbus_method_invocation_return_value(invocation, 1544 | g_variant_new("(s)", response)); 1545 | g_free(response); 1546 | 1547 | return; 1548 | } 1549 | else 1550 | if (g_strcmp0(method_name, "query_view_app_id_xwayland_net_wm_name") == 1551 | 0) 1552 | { 1553 | uint view_id; 1554 | gchar* response = "nullptr"; 1555 | wayfire_view view; 1556 | bool free_response = false; 1557 | 1558 | g_variant_get(parameters, "(u)", &view_id); 1559 | view = get_view_from_view_id(view_id); 1560 | 1561 | if (view) { 1562 | auto wlr_surf = view->get_wlr_surface(); 1563 | if (!wlr_surf) { 1564 | g_dbus_method_invocation_return_value(invocation, 1565 | g_variant_new("(s)", response)); 1566 | 1567 | return; 1568 | } 1569 | 1570 | if (wlr_surface_is_xwayland_surface(wlr_surf)) { 1571 | struct wlr_xwayland_surface* xsurf; 1572 | xsurf = wlr_xwayland_surface_from_wlr_surface(wlr_surf); 1573 | if (!xsurf) { 1574 | g_dbus_method_invocation_return_value(invocation, 1575 | g_variant_new("(s)", response)); 1576 | 1577 | return; 1578 | } 1579 | 1580 | g_assert(xsurf != NULL); 1581 | std::string wm_name_app_id = nonull(xsurf->instance); 1582 | response = g_strdup_printf(wm_name_app_id.c_str()); 1583 | free_response = true; 1584 | } 1585 | } 1586 | 1587 | if (free_response) { 1588 | g_free(response); 1589 | } 1590 | 1591 | g_dbus_method_invocation_return_value(invocation, 1592 | g_variant_new("(s)", response)); 1593 | 1594 | return; 1595 | } 1596 | else 1597 | if (g_strcmp0(method_name, "query_view_title") == 0) 1598 | { 1599 | uint view_id; 1600 | gchar* response = "nullptr"; 1601 | wayfire_view view; 1602 | 1603 | g_variant_get(parameters, "(u)", &view_id); 1604 | view = get_view_from_view_id(view_id); 1605 | 1606 | if (!check_view_toplevel(view)) { 1607 | g_dbus_method_invocation_return_value(invocation, 1608 | g_variant_new("(s)", response)); 1609 | 1610 | return; 1611 | } 1612 | 1613 | response = g_strdup_printf(view->get_title().c_str()); 1614 | g_dbus_method_invocation_return_value(invocation, 1615 | g_variant_new("(s)", response)); 1616 | g_free(response); 1617 | 1618 | return; 1619 | } 1620 | else 1621 | if (g_strcmp0(method_name, "query_view_attention") == 0) 1622 | { 1623 | uint view_id; 1624 | bool attention = false; 1625 | wayfire_view view; 1626 | 1627 | g_variant_get(parameters, "(u)", &view_id); 1628 | view = get_view_from_view_id(view_id); 1629 | if (!check_view_toplevel(view)) { 1630 | return; 1631 | } 1632 | 1633 | if (view->has_data("view-demands-attention")) { 1634 | attention = true; 1635 | } 1636 | 1637 | g_dbus_method_invocation_return_value(invocation, 1638 | g_variant_new("(b)", attention)); 1639 | 1640 | return; 1641 | } 1642 | else 1643 | if (g_strcmp0(method_name, "query_xwayland_display") == 0) 1644 | { 1645 | const char* xdisplay = core.get_xwayland_display().c_str(); 1646 | 1647 | g_dbus_method_invocation_return_value(invocation, 1648 | g_variant_new("(s)", xdisplay)); 1649 | 1650 | return; 1651 | } 1652 | else 1653 | if (g_strcmp0(method_name, "query_view_xwayland_wid") == 0) 1654 | { 1655 | uint view_id; 1656 | wayfire_view view; 1657 | 1658 | g_variant_get(parameters, "(u)", &view_id); 1659 | view = get_view_from_view_id(view_id); 1660 | 1661 | if (!view) { 1662 | g_dbus_method_invocation_return_value(invocation, 1663 | g_variant_new("(u)", 0)); 1664 | 1665 | return; 1666 | } 1667 | 1668 | if (xwayland_enabled == 1) { 1669 | auto main_wlr_surface = view->get_main_surface()->get_wlr_surface(); 1670 | if (!main_wlr_surface) { 1671 | g_dbus_method_invocation_return_value(invocation, 1672 | g_variant_new("(u)", 0)); 1673 | 1674 | return; 1675 | } 1676 | 1677 | if (wlr_surface_is_xwayland_surface(main_wlr_surface)) { 1678 | #ifdef DBUS_PLUGIN_DEBUG 1679 | LOG(wf::log::LOG_LEVEL_DEBUG, "xwayland is the surface type."); 1680 | #endif 1681 | struct wlr_xwayland_surface* main_xsurf; 1682 | main_xsurf = wlr_xwayland_surface_from_wlr_surface(main_wlr_surface); 1683 | g_dbus_method_invocation_return_value( 1684 | invocation, g_variant_new("(u)", main_xsurf->window_id)); 1685 | 1686 | return; 1687 | } 1688 | } 1689 | 1690 | g_dbus_method_invocation_return_value(invocation, g_variant_new("(u)", 0)); 1691 | 1692 | return; 1693 | } 1694 | else 1695 | if (g_strcmp0(method_name, "query_view_xwayland_atom_cardinal") == 0) 1696 | { 1697 | uint view_id; 1698 | uint atom_value_cardinal = 0; 1699 | gchar* atom_name; 1700 | wayfire_view view; 1701 | 1702 | g_variant_get(parameters, "(us)", &view_id, &atom_name); 1703 | view = get_view_from_view_id(view_id); 1704 | 1705 | if (!view) { 1706 | g_dbus_method_invocation_return_value(invocation, 1707 | g_variant_new("(u)", 0)); 1708 | 1709 | return; 1710 | } 1711 | 1712 | auto main_wlr_surface = view->get_main_surface()->get_wlr_surface(); 1713 | if (!main_wlr_surface) { 1714 | g_dbus_method_invocation_return_value(invocation, 1715 | g_variant_new("(u)", 0)); 1716 | 1717 | return; 1718 | } 1719 | 1720 | if ((xwayland_enabled != 1) || 1721 | !wlr_surface_is_xwayland_surface(main_wlr_surface)) { 1722 | g_dbus_method_invocation_return_value(invocation, 1723 | g_variant_new("(u)", 0)); 1724 | 1725 | return; 1726 | } 1727 | 1728 | struct wlr_xwayland_surface* main_xsurf; 1729 | main_xsurf = wlr_xwayland_surface_from_wlr_surface(main_wlr_surface); 1730 | 1731 | const char* xdisplay = core.get_xwayland_display().c_str(); 1732 | int screen; 1733 | xcb_connection_t* conn = xcb_connect(xdisplay, &screen); 1734 | xcb_intern_atom_cookie_t atom_cookie; 1735 | xcb_atom_t atom; 1736 | xcb_intern_atom_reply_t* reply; 1737 | atom_cookie = xcb_intern_atom(conn, 0, strlen(atom_name), atom_name); 1738 | reply = xcb_intern_atom_reply(conn, atom_cookie, NULL); 1739 | if (reply != NULL) { 1740 | atom = reply->atom; 1741 | free(reply); 1742 | } 1743 | else 1744 | { 1745 | #ifdef DBUS_PLUGIN_DEBUG 1746 | LOG(wf::log::LOG_LEVEL_DEBUG, "reply for querying the atom is empty."); 1747 | #endif 1748 | g_dbus_method_invocation_return_value( 1749 | invocation, g_variant_new("(u)", atom_value_cardinal)); 1750 | 1751 | return; 1752 | } 1753 | 1754 | xcb_get_property_cookie_t reply_cookie; 1755 | xcb_get_property_reply_t* reply_value; 1756 | reply_cookie = xcb_get_property(conn, 0, main_xsurf->window_id, atom, 1757 | XCB_ATOM_ANY, 0, 2048); 1758 | reply_value = xcb_get_property_reply(conn, reply_cookie, NULL); 1759 | xcb_disconnect(conn); 1760 | 1761 | if (reply_value->type == XCB_ATOM_CARDINAL) { 1762 | uint* uvalue = (uint*)xcb_get_property_value(reply_value); 1763 | atom_value_cardinal = *uvalue; 1764 | #ifdef DBUS_PLUGIN_DEBUG 1765 | LOG(wf::log::LOG_LEVEL_DEBUG, "value to uint.", atom_value_cardinal); 1766 | #endif 1767 | } 1768 | 1769 | #ifdef DBUS_PLUGIN_DEBUG 1770 | else 1771 | { 1772 | LOG(wf::log::LOG_LEVEL_DEBUG, "requested value is not a cardinal"); 1773 | } 1774 | #endif 1775 | 1776 | g_dbus_method_invocation_return_value( 1777 | invocation, g_variant_new("(u)", atom_value_cardinal)); 1778 | 1779 | return; 1780 | } 1781 | else 1782 | if (g_strcmp0(method_name, "query_view_xwayland_atom_string") == 0) 1783 | { 1784 | uint view_id; 1785 | gchar* atom_name; 1786 | gchar* atom_value_string = "No atom value received."; 1787 | 1788 | g_variant_get(parameters, "(us)", &view_id, &atom_name); 1789 | 1790 | wayfire_view view = get_view_from_view_id(view_id); 1791 | 1792 | if (!view) { 1793 | g_dbus_method_invocation_return_value( 1794 | invocation, g_variant_new("(s)", "View not found.")); 1795 | 1796 | return; 1797 | } 1798 | 1799 | auto main_wlr_surface = view->get_main_surface()->get_wlr_surface(); 1800 | 1801 | if (!main_wlr_surface) { 1802 | g_dbus_method_invocation_return_value( 1803 | invocation, g_variant_new("(s)", "main_wlr_surface not found.")); 1804 | 1805 | return; 1806 | } 1807 | 1808 | if ((xwayland_enabled != 1) || 1809 | !wlr_surface_is_xwayland_surface(main_wlr_surface)) { 1810 | g_dbus_method_invocation_return_value( 1811 | invocation, g_variant_new("(s)", "Not an xwayland surface.")); 1812 | 1813 | return; 1814 | } 1815 | 1816 | struct wlr_xwayland_surface* main_xsurf; 1817 | 1818 | main_xsurf = wlr_xwayland_surface_from_wlr_surface(main_wlr_surface); 1819 | 1820 | const char* xdisplay = core.get_xwayland_display().c_str(); 1821 | int screen; 1822 | xcb_connection_t* conn = xcb_connect(xdisplay, &screen); 1823 | xcb_intern_atom_cookie_t atom_cookie; 1824 | xcb_atom_t atom; 1825 | xcb_intern_atom_reply_t* reply; 1826 | atom_cookie = xcb_intern_atom(conn, 0, strlen(atom_name), atom_name); 1827 | reply = xcb_intern_atom_reply(conn, atom_cookie, NULL); 1828 | if (reply != NULL) { 1829 | atom = reply->atom; 1830 | free(reply); 1831 | } 1832 | else 1833 | { 1834 | g_dbus_method_invocation_return_value( 1835 | invocation, 1836 | g_variant_new("(s)", "reply for querying the atom is empty.")); 1837 | 1838 | return; 1839 | } 1840 | 1841 | xcb_get_property_cookie_t reply_cookie = xcb_get_property( 1842 | conn, 0, main_xsurf->window_id, atom, XCB_ATOM_ANY, 0, 2048); 1843 | xcb_get_property_reply_t* reply_value = 1844 | xcb_get_property_reply(conn, reply_cookie, NULL); 1845 | 1846 | char* value = static_cast<char*> (xcb_get_property_value(reply_value)); 1847 | 1848 | xcb_disconnect(conn); 1849 | 1850 | if (reply_value->type != XCB_ATOM_CARDINAL) { 1851 | atom_value_string = value; 1852 | #ifdef DBUS_PLUGIN_DEBUG 1853 | LOG(wf::log::LOG_LEVEL_DEBUG, "value to char.", atom_value_string); 1854 | #endif 1855 | g_dbus_method_invocation_return_value( 1856 | invocation, g_variant_new("(s)", atom_value_string)); 1857 | 1858 | return; 1859 | } 1860 | else 1861 | { 1862 | g_dbus_method_invocation_return_value( 1863 | invocation, 1864 | g_variant_new("(s)", "XCB_ATOM_CARDINAL type requested.")); 1865 | 1866 | return; 1867 | } 1868 | } 1869 | else 1870 | if (g_strcmp0(method_name, "query_view_credentials") == 0) 1871 | { 1872 | uint view_id; 1873 | pid_t pid = 0; 1874 | uid_t uid = 0; 1875 | gid_t gid = 0; 1876 | wayfire_view view; 1877 | 1878 | g_variant_get(parameters, "(u)", &view_id); 1879 | view = get_view_from_view_id(view_id); 1880 | 1881 | if (!view) { 1882 | g_dbus_method_invocation_return_value(invocation, 1883 | g_variant_new("(iuu)", 0, 0, 0)); 1884 | 1885 | return; 1886 | } 1887 | 1888 | if (xwayland_enabled == 1) { 1889 | auto main_surface = view->get_main_surface()->get_wlr_surface(); 1890 | if (!main_surface) { 1891 | g_dbus_method_invocation_return_value(invocation, 1892 | g_variant_new("(iuu)", 0, 0, 0)); 1893 | 1894 | return; 1895 | } 1896 | 1897 | if (wlr_surface_is_xwayland_surface(main_surface)) { 1898 | struct wlr_xwayland_surface* main_xsurf; 1899 | xcb_res_client_id_spec_t spec = {0}; 1900 | xcb_generic_error_t* err = NULL; 1901 | xcb_res_query_client_ids_cookie_t cookie; 1902 | xcb_res_query_client_ids_reply_t* reply; 1903 | int screen; 1904 | 1905 | const char* xdisplay = core.get_xwayland_display().c_str(); 1906 | xcb_connection_t* conn = xcb_connect(xdisplay, &screen); 1907 | 1908 | main_xsurf = wlr_xwayland_surface_from_wlr_surface(main_surface); 1909 | spec.client = main_xsurf->window_id; 1910 | spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; 1911 | cookie = xcb_res_query_client_ids(conn, 1, &spec); 1912 | reply = xcb_res_query_client_ids_reply(conn, cookie, &err); 1913 | 1914 | if (reply == NULL) { 1915 | #ifdef DBUS_PLUGIN_DEBUG 1916 | LOG(wf::log::LOG_LEVEL_DEBUG, 1917 | "could not get pid from xserver, empty reply"); 1918 | #endif 1919 | } 1920 | else 1921 | { 1922 | xcb_res_client_id_value_iterator_t it; 1923 | it = xcb_res_query_client_ids_ids_iterator(reply); 1924 | for (; it.rem; xcb_res_client_id_value_next(&it)) 1925 | { 1926 | spec = it.data->spec; 1927 | if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) { 1928 | pid = *xcb_res_client_id_value_value(it.data); 1929 | break; 1930 | } 1931 | } 1932 | 1933 | free(reply); 1934 | } 1935 | 1936 | xcb_disconnect(conn); 1937 | 1938 | if (pid != 0) { 1939 | LOG(wf::log::LOG_LEVEL_DEBUG, 1940 | "returning xwayland window credentials."); 1941 | g_dbus_method_invocation_return_value( 1942 | invocation, g_variant_new("(iuu)", pid, uid, gid)); 1943 | 1944 | return; 1945 | } 1946 | } 1947 | } 1948 | 1949 | #ifdef DBUS_PLUGIN_DEBUG 1950 | LOG(wf::log::LOG_LEVEL_DEBUG, "returning standard credentials."); 1951 | #endif 1952 | wl_client_get_credentials(view->get_client(), &pid, &uid, &gid); 1953 | g_dbus_method_invocation_return_value( 1954 | invocation, g_variant_new("(iuu)", pid, uid, gid)); 1955 | 1956 | return; 1957 | } 1958 | else 1959 | if (g_strcmp0(method_name, "query_view_above") == 0) 1960 | { 1961 | wayfire_view view; 1962 | uint view_id; 1963 | bool above; 1964 | 1965 | g_variant_get(parameters, "(u)", &view_id); 1966 | view = get_view_from_view_id(view_id); 1967 | above = false; 1968 | 1969 | if (view) { 1970 | if (view->has_data("wm-actions-above")) { 1971 | above = true; 1972 | } 1973 | } 1974 | 1975 | #ifdef DBUS_PLUGIN_DEBUG 1976 | else 1977 | { 1978 | LOG(wf::log::LOG_LEVEL_DEBUG, "query_view_above no view"); 1979 | } 1980 | #endif 1981 | g_dbus_method_invocation_return_value(invocation, 1982 | g_variant_new("(b)", above)); 1983 | 1984 | return; 1985 | } 1986 | else 1987 | if (g_strcmp0(method_name, "query_view_maximized") == 0) 1988 | { 1989 | wayfire_view view; 1990 | uint view_id; 1991 | bool response = false; 1992 | 1993 | g_variant_get(parameters, "(u)", &view_id); 1994 | view = get_view_from_view_id(view_id); 1995 | 1996 | if (view) { 1997 | response = (view->tiled_edges == wf::TILED_EDGES_ALL); 1998 | } 1999 | 2000 | #ifdef DBUS_PLUGIN_DEBUG 2001 | else 2002 | { 2003 | LOG(wf::log::LOG_LEVEL_DEBUG, "query_view_maximized no view"); 2004 | } 2005 | #endif 2006 | g_dbus_method_invocation_return_value(invocation, 2007 | g_variant_new("(b)", response)); 2008 | 2009 | return; 2010 | } 2011 | 2012 | else 2013 | if (g_strcmp0(method_name, "query_view_active") == 0) 2014 | { 2015 | wayfire_view view; 2016 | uint view_id; 2017 | bool response = false; 2018 | 2019 | g_variant_get(parameters, "(u)", &view_id); 2020 | view = get_view_from_view_id(view_id); 2021 | 2022 | if (view) { 2023 | response = view->activated; 2024 | } 2025 | 2026 | #ifdef DBUS_PLUGIN_DEBUG 2027 | else 2028 | { 2029 | LOG(wf::log::LOG_LEVEL_DEBUG, "query_view_active no view"); 2030 | } 2031 | #endif 2032 | g_dbus_method_invocation_return_value(invocation, 2033 | g_variant_new("(b)", response)); 2034 | 2035 | return; 2036 | } 2037 | 2038 | else 2039 | if (g_strcmp0(method_name, "query_view_minimized") == 0) 2040 | { 2041 | wayfire_view view; 2042 | uint view_id; 2043 | bool response = false; 2044 | 2045 | g_variant_get(parameters, "(u)", &view_id); 2046 | view = get_view_from_view_id(view_id); 2047 | 2048 | if (view) { 2049 | response = view->minimized; 2050 | } 2051 | 2052 | #ifdef DBUS_PLUGIN_DEBUG 2053 | else 2054 | { 2055 | LOG(wf::log::LOG_LEVEL_DEBUG, "query_view_minimized no view"); 2056 | } 2057 | #endif 2058 | g_dbus_method_invocation_return_value(invocation, 2059 | g_variant_new("(b)", response)); 2060 | 2061 | return; 2062 | } 2063 | 2064 | else 2065 | if (g_strcmp0(method_name, "query_view_fullscreen") == 0) 2066 | { 2067 | uint view_id; 2068 | bool response = false; 2069 | wayfire_view view; 2070 | 2071 | g_variant_get(parameters, "(u)", &view_id); 2072 | view = get_view_from_view_id(view_id); 2073 | 2074 | if (view) { 2075 | response = view->fullscreen; 2076 | } 2077 | 2078 | #ifdef DBUS_PLUGIN_DEBUG 2079 | else 2080 | { 2081 | LOG(wf::log::LOG_LEVEL_DEBUG, "query_view_fullscreen no view"); 2082 | } 2083 | #endif 2084 | g_dbus_method_invocation_return_value(invocation, 2085 | g_variant_new("(b)", response)); 2086 | 2087 | return; 2088 | } 2089 | else 2090 | if (g_strcmp0(method_name, "query_view_output") == 0) 2091 | { 2092 | uint view_id; 2093 | uint output_id = 0; 2094 | wayfire_view view; 2095 | 2096 | g_variant_get(parameters, "(u)", &view_id); 2097 | view = get_view_from_view_id(view_id); 2098 | 2099 | if (view) { 2100 | if (view->get_output()) { 2101 | output_id = view->get_output()->get_id(); 2102 | } 2103 | 2104 | #ifdef DBUS_PLUGIN_DEBUG 2105 | 2106 | else 2107 | { 2108 | g_warning("No output for view."); 2109 | } 2110 | #endif 2111 | } 2112 | 2113 | g_dbus_method_invocation_return_value(invocation, 2114 | g_variant_new("(u)", output_id)); 2115 | 2116 | return; 2117 | } 2118 | else 2119 | if (g_strcmp0(method_name, "query_view_workspaces") == 0) 2120 | { 2121 | #ifdef DBUS_PLUGIN_DEBUG 2122 | LOG(wf::log::LOG_LEVEL_DEBUG, "query_view_workspaces "); 2123 | #endif 2124 | 2125 | uint view_id; 2126 | double area; 2127 | GVariantBuilder builder; 2128 | GVariant* value; 2129 | wf::geometry_t workspace_relative_geometry; 2130 | wlr_box view_relative_geometry; 2131 | wf::geometry_t intersection; 2132 | wf::dimensions_t workspaces; 2133 | wf::output_t* output; 2134 | 2135 | g_variant_get(parameters, "(u)", &view_id); 2136 | wayfire_view view = get_view_from_view_id(view_id); 2137 | 2138 | if (!check_view_toplevel(view)) { 2139 | #ifdef DBUS_PLUGIN_DEBUG 2140 | 2141 | LOG(wf::log::LOG_LEVEL_DEBUG, "query_view_workspaces no view"); 2142 | #endif 2143 | g_dbus_method_invocation_return_value(invocation, NULL); 2144 | 2145 | return; 2146 | } 2147 | 2148 | workspaces = core.get_active_output()->workspace->get_workspace_grid_size(); 2149 | 2150 | view_relative_geometry = view->get_bounding_box(); 2151 | output = view->get_output(); 2152 | 2153 | g_variant_builder_init(&builder, G_VARIANT_TYPE("a(ii)")); 2154 | 2155 | for (int horizontal_workspace = 0; horizontal_workspace < workspaces.width; 2156 | horizontal_workspace++) 2157 | { 2158 | for (int vertical_workspace = 0; vertical_workspace < workspaces.height; 2159 | vertical_workspace++) 2160 | { 2161 | wf::point_t ws = {horizontal_workspace, vertical_workspace}; 2162 | if (output->workspace->view_visible_on(view, ws)) { 2163 | workspace_relative_geometry = output->render->get_ws_box(ws); 2164 | intersection = wf::geometry_intersection(view_relative_geometry, 2165 | workspace_relative_geometry); 2166 | area = 1.0 * intersection.width * intersection.height; 2167 | area /= 1.0 * view_relative_geometry.width * 2168 | view_relative_geometry.height; 2169 | 2170 | if (area > 0.1) { 2171 | g_variant_builder_add(&builder, "(ii)", horizontal_workspace, 2172 | vertical_workspace); 2173 | } 2174 | } 2175 | } 2176 | } 2177 | 2178 | value = g_variant_new("(a(ii))", &builder); 2179 | g_dbus_method_invocation_return_value(invocation, value); 2180 | 2181 | return; 2182 | } 2183 | else 2184 | if (g_strcmp0(method_name, "query_view_group_leader") == 0) 2185 | { 2186 | uint view_id; 2187 | uint group_leader_view_id; 2188 | wayfire_view view; 2189 | 2190 | g_variant_get(parameters, "(u)", &view_id); 2191 | group_leader_view_id = view_id; 2192 | view = get_view_from_view_id(view_id); 2193 | 2194 | if (view) { 2195 | while (view->parent) 2196 | { 2197 | view = view->parent; 2198 | } 2199 | 2200 | group_leader_view_id = view->get_id(); 2201 | #ifdef DBUS_PLUGIN_DEBUG 2202 | LOG(wf::log::LOG_LEVEL_DEBUG, "query_view_group_leader found returning"); 2203 | #endif 2204 | } 2205 | 2206 | g_dbus_method_invocation_return_value( 2207 | invocation, g_variant_new("(u)", group_leader_view_id)); 2208 | 2209 | return; 2210 | } 2211 | else 2212 | if (g_strcmp0(method_name, "query_view_role") == 0) 2213 | { 2214 | uint view_id; 2215 | uint response = 0; 2216 | bool is_modal_dialog; 2217 | wayfire_view view; 2218 | 2219 | g_variant_get(parameters, "(u)", &view_id); 2220 | view = get_view_from_view_id(view_id); 2221 | 2222 | if (view) { 2223 | if (view->is_mapped()) { 2224 | is_modal_dialog = view->has_data("gtk-shell-modal"); 2225 | 2226 | if ((view->role == wf::VIEW_ROLE_TOPLEVEL) && !is_modal_dialog) { 2227 | response = 1; 2228 | } 2229 | 2230 | else 2231 | if (view->role == wf::VIEW_ROLE_DESKTOP_ENVIRONMENT) 2232 | { 2233 | response = 2; 2234 | } 2235 | 2236 | else 2237 | if (view->role == wf::VIEW_ROLE_UNMANAGED) 2238 | { 2239 | response = 3; 2240 | } 2241 | } 2242 | } 2243 | 2244 | g_dbus_method_invocation_return_value(invocation, 2245 | g_variant_new("(u)", response)); 2246 | 2247 | return; 2248 | } 2249 | else 2250 | if (g_strcmp0(method_name, "query_view_test_data") == 0) 2251 | { 2252 | uint view_id; 2253 | wayfire_view view; 2254 | 2255 | g_variant_get(parameters, "(u)", &view_id); 2256 | view = get_view_from_view_id(view_id); 2257 | 2258 | if (!check_view_toplevel(view)) 2259 | { 2260 | g_dbus_method_invocation_return_value(invocation, 2261 | g_variant_new("(uu)", 0, 0)); 2262 | 2263 | return; 2264 | } 2265 | 2266 | auto wlr_surf = view->get_wlr_surface(); 2267 | if (!wlr_surf) { 2268 | g_dbus_method_invocation_return_value(invocation, 2269 | g_variant_new("(uu)", 0, 0)); 2270 | 2271 | return; 2272 | } 2273 | 2274 | if (wlr_surface_is_xwayland_surface(wlr_surf)) { 2275 | struct wlr_xwayland_surface* xsurf; 2276 | xsurf = wlr_xwayland_surface_from_wlr_surface(wlr_surf); 2277 | g_dbus_method_invocation_return_value( 2278 | invocation, g_variant_new("(uu)", xsurf->width, xsurf->height)); 2279 | } 2280 | 2281 | return; 2282 | } 2283 | 2284 | /*************** Other Actions ****************/ 2285 | else 2286 | if (g_strcmp0(method_name, "inhibit_output_start") == 0) 2287 | { 2288 | g_variant_unref(parameters); 2289 | } 2290 | else 2291 | if (g_strcmp0(method_name, "inhibit_output_stop") == 0) 2292 | { 2293 | g_variant_unref(parameters); 2294 | } 2295 | else 2296 | if (g_strcmp0(method_name, "trigger_show_desktop") == 0) 2297 | { 2298 | g_variant_unref(parameters); 2299 | } 2300 | else 2301 | if (g_strcmp0(method_name, "trigger_show_overview") == 0) 2302 | { 2303 | g_variant_unref(parameters); 2304 | } 2305 | } 2306 | 2307 | static GVariant* 2308 | handle_get_property (GDBusConnection* connection, 2309 | const gchar* sender, 2310 | const gchar* object_path, 2311 | const gchar* interface_name, 2312 | const gchar* property_name, GError** error, 2313 | gpointer user_data) 2314 | { 2315 | // returning nullptr would crash compositor 2316 | GVariant* ret = g_variant_new_string("nullptr"); 2317 | 2318 | // kept as an example 2319 | // if (g_strcmp0(property_name, "view_vector_ids") == 0) 2320 | // { 2321 | // std::vector<nonstd::observer_ptr<wf::view_interface_t>> view_vector = 2322 | // core.get_all_views(); 2323 | 2324 | // GVariantBuilder builder; 2325 | // g_variant_builder_init(&builder, G_VARIANT_TYPE("au")); 2326 | // for (auto it = begin(view_vector); it != end(view_vector); ++it) 2327 | // g_variant_builder_add(&builder, "u", it->get()->get_id()); 2328 | // ret = g_variant_builder_end(&builder); 2329 | // } 2330 | 2331 | /* unused */ 2332 | return ret; 2333 | } 2334 | 2335 | static gboolean 2336 | handle_set_property (GDBusConnection* connection, 2337 | const gchar* sender, 2338 | const gchar* object_path, 2339 | const gchar* interface_name, 2340 | const gchar* property_name, GVariant* value, 2341 | GError** error, gpointer user_data) 2342 | { 2343 | /* unused */ 2344 | return false; 2345 | } 2346 | 2347 | static const GDBusInterfaceVTable interface_vtable = { 2348 | handle_method_call, handle_get_property, handle_set_property, {0} 2349 | }; 2350 | 2351 | static gboolean 2352 | bus_emit_signal (gchar* signal_name, GVariant* signal_data) 2353 | { 2354 | GError* local_error = NULL; 2355 | if (!dbus_connection) { 2356 | if (signal_data != nullptr) { 2357 | g_variant_unref(signal_data); 2358 | } 2359 | 2360 | return true; 2361 | } 2362 | 2363 | g_dbus_connection_emit_signal( 2364 | dbus_connection, nullptr, "/org/wayland/compositor", 2365 | "org.wayland.compositor", signal_name, signal_data, &local_error); 2366 | g_assert_no_error(local_error); 2367 | 2368 | if (signal_data != nullptr) { 2369 | g_variant_unref(signal_data); 2370 | } 2371 | 2372 | return true; 2373 | } 2374 | 2375 | static void 2376 | on_bus_acquired (GDBusConnection* connection, const gchar* name, 2377 | gpointer user_data) 2378 | { 2379 | uint registration_id; 2380 | 2381 | dbus_connection = connection; 2382 | registration_id = g_dbus_connection_register_object( 2383 | connection, "/org/wayland/compositor", introspection_data->interfaces[0], 2384 | &interface_vtable, nullptr, nullptr, nullptr); 2385 | #ifdef DBUS_PLUGIN_DEBUG 2386 | LOG(wf::log::LOG_LEVEL_DEBUG, "Acquired the Bus"); 2387 | #endif 2388 | } 2389 | 2390 | static void 2391 | on_name_acquired (GDBusConnection* connection, const gchar* name, 2392 | gpointer user_data) 2393 | { 2394 | #ifdef DBUS_PLUGIN_DEBUG 2395 | LOG(wf::log::LOG_LEVEL_DEBUG, 2396 | "Acquired the name " + std::string(name) + "on the session bus\n"); 2397 | #endif 2398 | } 2399 | 2400 | static void 2401 | on_name_lost (GDBusConnection* connection, const gchar* name, 2402 | gpointer user_data) 2403 | { 2404 | #ifdef DBUS_PLUGIN_DEBUG 2405 | LOG(wf::log::LOG_LEVEL_DEBUG, 2406 | "Lost the name " + std::string(name) + "on the session bus"); 2407 | #endif 2408 | } 2409 | 2410 | static void 2411 | acquire_bus () 2412 | { 2413 | GBusNameOwnerFlags flags; 2414 | // flags = G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE; 2415 | introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, nullptr); 2416 | 2417 | owner_id = g_bus_own_name(G_BUS_TYPE_SESSION, "org.wayland.compositor", flags, 2418 | on_bus_acquired, on_name_acquired, on_name_lost, 2419 | nullptr, nullptr); 2420 | } 2421 | --------------------------------------------------------------------------------