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