File indexing completed on 2024-11-10 04:56:31
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #include "context.h" 0010 #include "events.h" 0011 #include "libinput_logging.h" 0012 0013 #include "core/session.h" 0014 #include "utils/udev.h" 0015 0016 #include <fcntl.h> 0017 #include <unistd.h> 0018 0019 #include <cerrno> 0020 0021 namespace KWin 0022 { 0023 namespace LibInput 0024 { 0025 0026 static void libinputLogHandler(libinput *libinput, libinput_log_priority priority, const char *format, va_list args) 0027 { 0028 char buf[1024]; 0029 if (std::vsnprintf(buf, 1023, format, args) <= 0) { 0030 return; 0031 } 0032 switch (priority) { 0033 case LIBINPUT_LOG_PRIORITY_DEBUG: 0034 qCDebug(KWIN_LIBINPUT) << "Libinput:" << buf; 0035 break; 0036 case LIBINPUT_LOG_PRIORITY_INFO: 0037 qCInfo(KWIN_LIBINPUT) << "Libinput:" << buf; 0038 break; 0039 case LIBINPUT_LOG_PRIORITY_ERROR: 0040 default: 0041 qCCritical(KWIN_LIBINPUT) << "Libinput:" << buf; 0042 break; 0043 } 0044 } 0045 0046 Context::Context(Session *session, std::unique_ptr<Udev> &&udev) 0047 : m_session(session) 0048 , m_libinput(libinput_udev_create_context(&Context::s_interface, this, *udev.get())) 0049 , m_suspended(false) 0050 , m_udev(std::move(udev)) 0051 { 0052 libinput_log_set_priority(m_libinput, LIBINPUT_LOG_PRIORITY_DEBUG); 0053 libinput_log_set_handler(m_libinput, &libinputLogHandler); 0054 } 0055 0056 Context::~Context() 0057 { 0058 if (m_libinput) { 0059 libinput_unref(m_libinput); 0060 } 0061 } 0062 0063 bool Context::initialize() 0064 { 0065 if (!isValid()) { 0066 return false; 0067 } 0068 return libinput_udev_assign_seat(m_libinput, m_session->seat().toUtf8().constData()) == 0; 0069 } 0070 0071 Session *Context::session() const 0072 { 0073 return m_session; 0074 } 0075 0076 int Context::fileDescriptor() 0077 { 0078 if (!isValid()) { 0079 return -1; 0080 } 0081 return libinput_get_fd(m_libinput); 0082 } 0083 0084 void Context::dispatch() 0085 { 0086 libinput_dispatch(m_libinput); 0087 } 0088 0089 const struct libinput_interface Context::s_interface = { 0090 Context::openRestrictedCallback, 0091 Context::closeRestrictedCallBack, 0092 }; 0093 0094 int Context::openRestrictedCallback(const char *path, int flags, void *user_data) 0095 { 0096 return ((Context *)user_data)->openRestricted(path, flags); 0097 } 0098 0099 void Context::closeRestrictedCallBack(int fd, void *user_data) 0100 { 0101 ((Context *)user_data)->closeRestricted(fd); 0102 } 0103 0104 int Context::openRestricted(const char *path, int flags) 0105 { 0106 int fd = m_session->openRestricted(path); 0107 if (fd < 0) { 0108 // failed 0109 return fd; 0110 } 0111 // adjust flags - based on Weston (logind-util.c) 0112 int fl = fcntl(fd, F_GETFL); 0113 auto errorHandling = [fd, this]() { 0114 close(fd); 0115 closeRestricted(fd); 0116 }; 0117 if (fl < 0) { 0118 errorHandling(); 0119 return -1; 0120 } 0121 0122 if (flags & O_NONBLOCK) { 0123 fl |= O_NONBLOCK; 0124 } 0125 0126 if (fcntl(fd, F_SETFL, fl) < 0) { 0127 errorHandling(); 0128 return -1; 0129 } 0130 0131 fl = fcntl(fd, F_GETFD); 0132 if (fl < 0) { 0133 errorHandling(); 0134 return -1; 0135 } 0136 0137 if (!(flags & O_CLOEXEC)) { 0138 fl &= ~FD_CLOEXEC; 0139 } 0140 0141 if (fcntl(fd, F_SETFD, fl) < 0) { 0142 errorHandling(); 0143 return -1; 0144 } 0145 return fd; 0146 } 0147 0148 void Context::closeRestricted(int fd) 0149 { 0150 m_session->closeRestricted(fd); 0151 } 0152 0153 std::unique_ptr<Event> Context::event() 0154 { 0155 return Event::create(libinput_get_event(m_libinput)); 0156 } 0157 0158 void Context::suspend() 0159 { 0160 if (m_suspended) { 0161 return; 0162 } 0163 libinput_suspend(m_libinput); 0164 m_suspended = true; 0165 } 0166 0167 void Context::resume() 0168 { 0169 if (!m_suspended) { 0170 return; 0171 } 0172 libinput_resume(m_libinput); 0173 m_suspended = false; 0174 } 0175 0176 } 0177 }