// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "components/exo/wayland/server.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "base/command_line.h" #include "base/files/file_path.h" #include "components/exo/display.h" #include "components/exo/wayland/wayland_display_output.h" #include "components/exo/wayland/wl_compositor.h" #include "components/exo/wayland/wl_data_device_manager.h" #include "components/exo/wayland/wl_output.h" #include "components/exo/wayland/wl_seat.h" #include "components/exo/wayland/wl_shm.h" #include "components/exo/wayland/wl_subcompositor.h" #include "components/exo/wayland/wp_presentation.h" #include "components/exo/wayland/wp_viewporter.h" #include "components/exo/wayland/zcr_alpha_compositing.h" #include "components/exo/wayland/zcr_secure_output.h" #include "components/exo/wayland/zcr_stylus.h" #include "components/exo/wayland/zcr_vsync_feedback.h" #include "ui/display/display.h" #include "ui/display/screen.h" #if defined(OS_CHROMEOS) #include "components/exo/wayland/wl_shell.h" #include "components/exo/wayland/zaura_shell.h" #include "components/exo/wayland/zcr_cursor_shapes.h" #include "components/exo/wayland/zcr_gaming_input.h" #include "components/exo/wayland/zcr_keyboard_configuration.h" #include "components/exo/wayland/zcr_keyboard_extension.h" #include "components/exo/wayland/zcr_notification_shell.h" #include "components/exo/wayland/zcr_remote_shell.h" #include "components/exo/wayland/zcr_stylus_tools.h" #include "components/exo/wayland/zwp_input_timestamps_manager.h" #include "components/exo/wayland/zwp_linux_explicit_synchronization.h" #include "components/exo/wayland/zwp_pointer_gestures.h" #include "components/exo/wayland/zwp_relative_pointer_manager.h" #include "components/exo/wayland/zwp_text_input_manager.h" #include "components/exo/wayland/zxdg_shell.h" #endif #if defined(USE_OZONE) #include #include "components/exo/wayland/zwp_linux_dmabuf.h" #endif #if defined(USE_FULLSCREEN_SHELL) #include #include "components/exo/wayland/zwp_fullscreen_shell.h" #endif namespace exo { namespace wayland { namespace switches { // This flag can be used to override the default wayland socket name. It is // useful when another wayland server is already running and using the // default name. constexpr char kWaylandServerSocket[] = "wayland-server-socket"; } namespace { // Default wayland socket name. const base::FilePath::CharType kSocketName[] = FILE_PATH_LITERAL("wayland-0"); // Group used for wayland socket. const char kWaylandSocketGroup[] = "wayland"; } // namespace //////////////////////////////////////////////////////////////////////////////// // Server, public: Server::Server(Display* display) : display_(display), wl_display_(wl_display_create()) { wl_global_create(wl_display_.get(), &wl_compositor_interface, kWlCompositorVersion, display_, bind_compositor); wl_global_create(wl_display_.get(), &wl_shm_interface, 1, display_, bind_shm); #if defined(USE_OZONE) wl_global_create(wl_display_.get(), &zwp_linux_dmabuf_v1_interface, kZwpLinuxDmabufVersion, display_, bind_linux_dmabuf); #endif wl_global_create(wl_display_.get(), &wl_subcompositor_interface, 1, display_, bind_subcompositor); display::Screen::GetScreen()->AddObserver(this); for (const auto& display : display::Screen::GetScreen()->GetAllDisplays()) OnDisplayAdded(display); wl_global_create(wl_display_.get(), &zcr_vsync_feedback_v1_interface, 1, display_, bind_vsync_feedback); wl_global_create(wl_display_.get(), &wl_data_device_manager_interface, kWlDataDeviceManagerVersion, display_, bind_data_device_manager); wl_global_create(wl_display_.get(), &wp_viewporter_interface, 1, display_, bind_viewporter); wl_global_create(wl_display_.get(), &wp_presentation_interface, 1, display_, bind_presentation); wl_global_create(wl_display_.get(), &zcr_secure_output_v1_interface, 1, display_, bind_secure_output); wl_global_create(wl_display_.get(), &zcr_alpha_compositing_v1_interface, 1, display_, bind_alpha_compositing); wl_global_create(wl_display_.get(), &zcr_stylus_v2_interface, 1, display_, bind_stylus_v2); wl_global_create(wl_display_.get(), &wl_seat_interface, kWlSeatVersion, display_->seat(), bind_seat); #if defined(OS_CHROMEOS) wl_global_create(wl_display_.get(), &wl_shell_interface, 1, display_, bind_shell); wl_global_create(wl_display_.get(), &zaura_shell_interface, kZAuraShellVersion, display_, bind_aura_shell); wl_global_create(wl_display_.get(), &zcr_cursor_shapes_v1_interface, 1, display_, bind_cursor_shapes); wl_global_create(wl_display_.get(), &zcr_gaming_input_v2_interface, 1, display_, bind_gaming_input); wl_global_create(wl_display_.get(), &zcr_keyboard_configuration_v1_interface, kZcrKeyboardConfigurationVersion, display_, bind_keyboard_configuration); wl_global_create(wl_display_.get(), &zcr_keyboard_extension_v1_interface, 1, display_, bind_keyboard_extension); wl_global_create(wl_display_.get(), &zcr_notification_shell_v1_interface, 1, display_, bind_notification_shell); wl_global_create(wl_display_.get(), &zcr_remote_shell_v1_interface, kZcrRemoteShellVersion, display_, bind_remote_shell); wl_global_create(wl_display_.get(), &zcr_stylus_tools_v1_interface, 1, display_, bind_stylus_tools); wl_global_create(wl_display_.get(), &zwp_input_timestamps_manager_v1_interface, 1, display_, bind_input_timestamps_manager); wl_global_create(wl_display_.get(), &zwp_pointer_gestures_v1_interface, 1, display_, bind_pointer_gestures); wl_global_create(wl_display_.get(), &zwp_relative_pointer_manager_v1_interface, 1, display_, bind_relative_pointer_manager); wl_global_create(wl_display_.get(), &zwp_text_input_manager_v1_interface, 1, display_, bind_text_input_manager); wl_global_create(wl_display_.get(), &zxdg_shell_v6_interface, 1, display_, bind_xdg_shell_v6); wl_global_create(wl_display_.get(), &zwp_linux_explicit_synchronization_v1_interface, 1, display_, bind_linux_explicit_synchronization); #endif #if defined(USE_FULLSCREEN_SHELL) wl_global_create(wl_display_.get(), &zwp_fullscreen_shell_v1_interface, 1, display_, bind_fullscreen_shell); #endif } Server::~Server() { display::Screen::GetScreen()->RemoveObserver(this); } // static std::unique_ptr Server::Create(Display* display) { std::unique_ptr server(new Server(display)); char* runtime_dir = getenv("XDG_RUNTIME_DIR"); if (!runtime_dir) { LOG(ERROR) << "XDG_RUNTIME_DIR not set in the environment"; return nullptr; } std::string socket_name(kSocketName); base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); if (command_line->HasSwitch(switches::kWaylandServerSocket)) { socket_name = command_line->GetSwitchValueASCII(switches::kWaylandServerSocket); } if (!server->AddSocket(socket_name.c_str())) { LOG(ERROR) << "Failed to add socket: " << socket_name; return nullptr; } base::FilePath socket_path = base::FilePath(runtime_dir).Append(socket_name); // Change permissions on the socket. struct group wayland_group; struct group* wayland_group_res = nullptr; char buf[10000]; if (HANDLE_EINTR(getgrnam_r(kWaylandSocketGroup, &wayland_group, buf, sizeof(buf), &wayland_group_res)) < 0) { PLOG(ERROR) << "getgrnam_r"; return nullptr; } if (wayland_group_res) { if (HANDLE_EINTR(chown(socket_path.MaybeAsASCII().c_str(), -1, wayland_group.gr_gid)) < 0) { PLOG(ERROR) << "chown"; return nullptr; } } else { LOG(WARNING) << "Group '" << kWaylandSocketGroup << "' not found"; } if (!base::SetPosixFilePermissions(socket_path, 0660)) { PLOG(ERROR) << "Could not set permissions: " << socket_path.value(); return nullptr; } return server; } bool Server::AddSocket(const std::string name) { DCHECK(!name.empty()); return !wl_display_add_socket(wl_display_.get(), name.c_str()); } int Server::GetFileDescriptor() const { wl_event_loop* event_loop = wl_display_get_event_loop(wl_display_.get()); DCHECK(event_loop); return wl_event_loop_get_fd(event_loop); } void Server::Dispatch(base::TimeDelta timeout) { wl_event_loop* event_loop = wl_display_get_event_loop(wl_display_.get()); DCHECK(event_loop); wl_event_loop_dispatch(event_loop, timeout.InMilliseconds()); } void Server::Flush() { wl_display_flush_clients(wl_display_.get()); } void Server::OnDisplayAdded(const display::Display& new_display) { auto output = std::make_unique(new_display.id()); output->set_global(wl_global_create(wl_display_.get(), &wl_output_interface, kWlOutputVersion, output.get(), bind_output)); DCHECK_EQ(outputs_.count(new_display.id()), 0u); outputs_.insert(std::make_pair(new_display.id(), std::move(output))); } void Server::OnDisplayRemoved(const display::Display& old_display) { DCHECK_EQ(outputs_.count(old_display.id()), 1u); outputs_.erase(old_display.id()); } } // namespace wayland } // namespace exo