File indexing completed on 2024-05-19 16:35:23
0001 /* 0002 SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org> 0003 SPDX-FileCopyrightText: 2020 David Edmundson <davidedmundson@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0006 */ 0007 #include "plasmashell_interface.h" 0008 #include "display.h" 0009 #include "surface_interface.h" 0010 #include "utils.h" 0011 0012 #include <qwayland-server-plasma-shell.h> 0013 0014 namespace KWaylandServer 0015 { 0016 static const quint32 s_version = 8; 0017 static QList<PlasmaShellSurfaceInterface *> s_shellSurfaces; 0018 0019 class PlasmaShellInterfacePrivate : public QtWaylandServer::org_kde_plasma_shell 0020 { 0021 public: 0022 PlasmaShellInterfacePrivate(PlasmaShellInterface *q, Display *display); 0023 0024 private: 0025 void org_kde_plasma_shell_get_surface(Resource *resource, uint32_t id, struct ::wl_resource *surface) override; 0026 PlasmaShellInterface *q; 0027 }; 0028 0029 PlasmaShellInterfacePrivate::PlasmaShellInterfacePrivate(PlasmaShellInterface *_q, Display *display) 0030 : QtWaylandServer::org_kde_plasma_shell(*display, s_version) 0031 , q(_q) 0032 { 0033 } 0034 0035 class PlasmaShellSurfaceInterfacePrivate : public QtWaylandServer::org_kde_plasma_surface 0036 { 0037 public: 0038 PlasmaShellSurfaceInterfacePrivate(PlasmaShellSurfaceInterface *q, SurfaceInterface *surface, wl_resource *resource); 0039 0040 QPointer<SurfaceInterface> surface; 0041 PlasmaShellSurfaceInterface *q; 0042 QPoint m_globalPos; 0043 PlasmaShellSurfaceInterface::Role m_role = PlasmaShellSurfaceInterface::Role::Normal; 0044 PlasmaShellSurfaceInterface::PanelBehavior m_panelBehavior = PlasmaShellSurfaceInterface::PanelBehavior::AlwaysVisible; 0045 bool m_positionSet = false; 0046 bool m_skipTaskbar = false; 0047 bool m_skipSwitcher = false; 0048 bool m_panelTakesFocus = false; 0049 bool m_openUnderCursorRequested = false; 0050 0051 private: 0052 void org_kde_plasma_surface_destroy_resource(Resource *resource) override; 0053 void org_kde_plasma_surface_destroy(Resource *resource) override; 0054 void org_kde_plasma_surface_set_output(Resource *resource, struct ::wl_resource *output) override; 0055 void org_kde_plasma_surface_set_position(Resource *resource, int32_t x, int32_t y) override; 0056 void org_kde_plasma_surface_set_role(Resource *resource, uint32_t role) override; 0057 void org_kde_plasma_surface_set_panel_behavior(Resource *resource, uint32_t flag) override; 0058 void org_kde_plasma_surface_set_skip_taskbar(Resource *resource, uint32_t skip) override; 0059 void org_kde_plasma_surface_panel_auto_hide_hide(Resource *resource) override; 0060 void org_kde_plasma_surface_panel_auto_hide_show(Resource *resource) override; 0061 void org_kde_plasma_surface_set_panel_takes_focus(Resource *resource, uint32_t takes_focus) override; 0062 void org_kde_plasma_surface_set_skip_switcher(Resource *resource, uint32_t skip) override; 0063 void org_kde_plasma_surface_open_under_cursor(Resource *resource) override; 0064 }; 0065 0066 PlasmaShellInterface::PlasmaShellInterface(Display *display, QObject *parent) 0067 : QObject(parent) 0068 , d(new PlasmaShellInterfacePrivate(this, display)) 0069 { 0070 } 0071 0072 PlasmaShellInterface::~PlasmaShellInterface() = default; 0073 0074 void PlasmaShellInterfacePrivate::org_kde_plasma_shell_get_surface(QtWaylandServer::org_kde_plasma_shell::Resource *resource, 0075 uint32_t id, 0076 struct ::wl_resource *surface) 0077 { 0078 SurfaceInterface *s = SurfaceInterface::get(surface); 0079 if (!s) { 0080 wl_resource_post_error(resource->handle, 0, "Invalid surface"); 0081 return; 0082 } 0083 0084 if (PlasmaShellSurfaceInterface::get(s)) { 0085 wl_resource_post_error(resource->handle, 0, "org_kde_plasma_shell_surface already exists"); 0086 return; 0087 } 0088 0089 wl_resource *shell_resource = wl_resource_create(resource->client(), &org_kde_plasma_surface_interface, resource->version(), id); 0090 0091 auto shellSurface = new PlasmaShellSurfaceInterface(s, shell_resource); 0092 s_shellSurfaces.append(shellSurface); 0093 0094 QObject::connect(shellSurface, &QObject::destroyed, [shellSurface]() { 0095 s_shellSurfaces.removeOne(shellSurface); 0096 }); 0097 0098 Q_EMIT q->surfaceCreated(shellSurface); 0099 } 0100 0101 /********************************* 0102 * ShellSurfaceInterface 0103 *********************************/ 0104 PlasmaShellSurfaceInterfacePrivate::PlasmaShellSurfaceInterfacePrivate(PlasmaShellSurfaceInterface *_q, SurfaceInterface *surface, wl_resource *resource) 0105 : QtWaylandServer::org_kde_plasma_surface(resource) 0106 , surface(surface) 0107 , q(_q) 0108 { 0109 } 0110 0111 PlasmaShellSurfaceInterface::PlasmaShellSurfaceInterface(SurfaceInterface *surface, wl_resource *resource) 0112 : d(new PlasmaShellSurfaceInterfacePrivate(this, surface, resource)) 0113 { 0114 } 0115 0116 PlasmaShellSurfaceInterface::~PlasmaShellSurfaceInterface() = default; 0117 0118 SurfaceInterface *PlasmaShellSurfaceInterface::surface() const 0119 { 0120 return d->surface; 0121 } 0122 0123 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_destroy(Resource *resource) 0124 { 0125 wl_resource_destroy(resource->handle); 0126 } 0127 0128 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_destroy_resource(Resource *resource) 0129 { 0130 delete q; 0131 } 0132 0133 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_set_output(Resource *resource, struct ::wl_resource *output) 0134 { 0135 // TODO: implement 0136 } 0137 0138 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_set_position(Resource *resource, int32_t x, int32_t y) 0139 { 0140 QPoint globalPos(x, y); 0141 if (m_globalPos == globalPos && m_positionSet) { 0142 return; 0143 } 0144 m_positionSet = true; 0145 m_globalPos = globalPos; 0146 Q_EMIT q->positionChanged(); 0147 } 0148 0149 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_open_under_cursor(Resource *resource) 0150 { 0151 if (surface && surface->buffer()) { 0152 wl_resource_post_error(resource->handle, -1, "open_under_cursor: surface has a buffer"); 0153 } 0154 m_openUnderCursorRequested = true; 0155 Q_EMIT q->openUnderCursorRequested(); 0156 } 0157 0158 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_set_role(Resource *resource, uint32_t role) 0159 { 0160 PlasmaShellSurfaceInterface::Role r = PlasmaShellSurfaceInterface::Role::Normal; 0161 switch (role) { 0162 case role_desktop: 0163 r = PlasmaShellSurfaceInterface::Role::Desktop; 0164 break; 0165 case role_panel: 0166 r = PlasmaShellSurfaceInterface::Role::Panel; 0167 break; 0168 case role_onscreendisplay: 0169 r = PlasmaShellSurfaceInterface::Role::OnScreenDisplay; 0170 break; 0171 case role_notification: 0172 r = PlasmaShellSurfaceInterface::Role::Notification; 0173 break; 0174 case role_tooltip: 0175 r = PlasmaShellSurfaceInterface::Role::ToolTip; 0176 break; 0177 case role_criticalnotification: 0178 r = PlasmaShellSurfaceInterface::Role::CriticalNotification; 0179 break; 0180 case role_appletpopup: 0181 r = PlasmaShellSurfaceInterface::Role::AppletPopup; 0182 break; 0183 case role_normal: 0184 default: 0185 r = PlasmaShellSurfaceInterface::Role::Normal; 0186 break; 0187 } 0188 if (r == m_role) { 0189 return; 0190 } 0191 m_role = r; 0192 Q_EMIT q->roleChanged(); 0193 } 0194 0195 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_set_panel_behavior(Resource *resource, uint32_t flag) 0196 { 0197 PlasmaShellSurfaceInterface::PanelBehavior newBehavior = PlasmaShellSurfaceInterface::PanelBehavior::AlwaysVisible; 0198 switch (flag) { 0199 case panel_behavior_auto_hide: 0200 newBehavior = PlasmaShellSurfaceInterface::PanelBehavior::AutoHide; 0201 break; 0202 case panel_behavior_windows_can_cover: 0203 newBehavior = PlasmaShellSurfaceInterface::PanelBehavior::WindowsCanCover; 0204 break; 0205 case panel_behavior_windows_go_below: 0206 newBehavior = PlasmaShellSurfaceInterface::PanelBehavior::WindowsGoBelow; 0207 break; 0208 case panel_behavior_always_visible: 0209 default: 0210 break; 0211 } 0212 if (m_panelBehavior == newBehavior) { 0213 return; 0214 } 0215 m_panelBehavior = newBehavior; 0216 Q_EMIT q->panelBehaviorChanged(); 0217 } 0218 0219 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_set_skip_taskbar(Resource *resource, uint32_t skip) 0220 { 0221 m_skipTaskbar = (bool)skip; 0222 Q_EMIT q->skipTaskbarChanged(); 0223 } 0224 0225 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_set_skip_switcher(Resource *resource, uint32_t skip) 0226 { 0227 m_skipSwitcher = (bool)skip; 0228 Q_EMIT q->skipSwitcherChanged(); 0229 } 0230 0231 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_panel_auto_hide_hide(Resource *resource) 0232 { 0233 if (m_role != PlasmaShellSurfaceInterface::Role::Panel 0234 || (m_panelBehavior != PlasmaShellSurfaceInterface::PanelBehavior::AutoHide 0235 && m_panelBehavior != PlasmaShellSurfaceInterface::PanelBehavior::WindowsCanCover)) { 0236 wl_resource_post_error(resource->handle, error_panel_not_auto_hide, "Not an auto hide panel"); 0237 return; 0238 } 0239 Q_EMIT q->panelAutoHideHideRequested(); 0240 } 0241 0242 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_panel_auto_hide_show(Resource *resource) 0243 { 0244 if (m_role != PlasmaShellSurfaceInterface::Role::Panel || m_panelBehavior != PlasmaShellSurfaceInterface::PanelBehavior::AutoHide) { 0245 wl_resource_post_error(resource->handle, error_panel_not_auto_hide, "Not an auto hide panel"); 0246 return; 0247 } 0248 Q_EMIT q->panelAutoHideShowRequested(); 0249 } 0250 0251 void PlasmaShellSurfaceInterfacePrivate::org_kde_plasma_surface_set_panel_takes_focus(Resource *resource, uint32_t takesFocus) 0252 { 0253 if (m_panelTakesFocus == takesFocus) { 0254 return; 0255 } 0256 m_panelTakesFocus = takesFocus; 0257 Q_EMIT q->panelTakesFocusChanged(); 0258 } 0259 0260 QPoint PlasmaShellSurfaceInterface::position() const 0261 { 0262 return d->m_globalPos; 0263 } 0264 0265 PlasmaShellSurfaceInterface::Role PlasmaShellSurfaceInterface::role() const 0266 { 0267 return d->m_role; 0268 } 0269 0270 bool PlasmaShellSurfaceInterface::isPositionSet() const 0271 { 0272 return d->m_positionSet; 0273 } 0274 0275 bool PlasmaShellSurfaceInterface::wantsOpenUnderCursor() const 0276 { 0277 return d->m_openUnderCursorRequested; 0278 } 0279 0280 PlasmaShellSurfaceInterface::PanelBehavior PlasmaShellSurfaceInterface::panelBehavior() const 0281 { 0282 return d->m_panelBehavior; 0283 } 0284 0285 bool PlasmaShellSurfaceInterface::skipTaskbar() const 0286 { 0287 return d->m_skipTaskbar; 0288 } 0289 0290 bool PlasmaShellSurfaceInterface::skipSwitcher() const 0291 { 0292 return d->m_skipSwitcher; 0293 } 0294 0295 void PlasmaShellSurfaceInterface::hideAutoHidingPanel() 0296 { 0297 d->send_auto_hidden_panel_hidden(); 0298 } 0299 0300 void PlasmaShellSurfaceInterface::showAutoHidingPanel() 0301 { 0302 d->send_auto_hidden_panel_shown(); 0303 } 0304 0305 bool PlasmaShellSurfaceInterface::panelTakesFocus() const 0306 { 0307 return d->m_panelTakesFocus; 0308 } 0309 0310 PlasmaShellSurfaceInterface *PlasmaShellSurfaceInterface::get(wl_resource *native) 0311 { 0312 if (auto surfacePrivate = resource_cast<PlasmaShellSurfaceInterfacePrivate *>(native)) { 0313 return surfacePrivate->q; 0314 } 0315 return nullptr; 0316 } 0317 0318 PlasmaShellSurfaceInterface *PlasmaShellSurfaceInterface::get(SurfaceInterface *surface) 0319 { 0320 for (PlasmaShellSurfaceInterface *shellSurface : std::as_const(s_shellSurfaces)) { 0321 if (shellSurface->surface() == surface) { 0322 return shellSurface; 0323 } 0324 } 0325 return nullptr; 0326 } 0327 0328 }