diff --git a/dix/dix_priv.h b/dix/dix_priv.h index 8e6e406d6..4ca30056e 100644 --- a/dix/dix_priv.h +++ b/dix/dix_priv.h @@ -295,6 +295,18 @@ int dixScreenRaiseWindowDestroy(WindowPtr pWin); */ void dixScreenRaiseWindowPosition(WindowPtr pWin, uint32_t x, uint32_t y); +/* + * @brief call screen's close hooks + * @see dixScreenHookClose + * @param pScreen the screen being closed + * + * Call the pluggable screen close hooks that extensions might have registered on + * the screen, and finally call ScreenRec's CloseScreen proc. + * + * Should only be called by DIX itself. + */ +void dixScreenRaiseClose(ScreenPtr pScreen); + /* * @brief mark event ID as critical * @param event the event to add to the critical events bitmap diff --git a/dix/screen.c b/dix/screen.c index 4458c7250..f2da15240 100644 --- a/dix/screen.c +++ b/dix/screen.c @@ -18,9 +18,10 @@ void dixFreeScreen(ScreenPtr pScreen) FreeGCperDepth(pScreen); dixDestroyPixmap(pScreen->defaultStipple, 0); dixFreeScreenSpecificPrivates(pScreen); - pScreen->CloseScreen(pScreen); + dixScreenRaiseClose(pScreen); dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN); DeleteCallbackList(&pScreen->hookWindowDestroy); DeleteCallbackList(&pScreen->hookWindowPosition); + DeleteCallbackList(&pScreen->hookClose); free(pScreen); } diff --git a/dix/screen_hooks.c b/dix/screen_hooks.c index fb979b376..42650a50a 100644 --- a/dix/screen_hooks.c +++ b/dix/screen_hooks.c @@ -25,6 +25,7 @@ DECLARE_HOOK_PROC(WindowDestroy, hookWindowDestroy, XorgScreenWindowDestroyProcPtr); DECLARE_HOOK_PROC(WindowPosition, hookWindowPosition, XorgScreenWindowPositionProcPtr); +DECLARE_HOOK_PROC(Close, hookClose, XorgScreenCloseProcPtr); int dixScreenRaiseWindowDestroy(WindowPtr pWin) { @@ -56,3 +57,13 @@ void dixScreenRaiseWindowPosition(WindowPtr pWin, uint32_t x, uint32_t y) if (pScreen->PositionWindow) pScreen->PositionWindow(pWin, x, y); } + +void dixScreenRaiseClose(ScreenPtr pScreen) { + if (!pScreen) + return; + + CallCallbacks(&pScreen->hookClose, NULL); + + if (pScreen->CloseScreen) + pScreen->CloseScreen(pScreen); +} diff --git a/dix/screen_hooks_priv.h b/dix/screen_hooks_priv.h index 012adec15..00d1606ff 100644 --- a/dix/screen_hooks_priv.h +++ b/dix/screen_hooks_priv.h @@ -109,4 +109,40 @@ void dixScreenHookWindowPosition(ScreenPtr pScreen, void dixScreenUnhookWindowPosition(ScreenPtr pScreen, XorgScreenWindowPositionProcPtr func); +/* prototype of screen close notification handler */ +typedef void (*XorgScreenCloseProcPtr)(CallbackListPtr *pcbl, + ScreenPtr pScreen, + void *unused); + +/** + * @brief register a screen close notify hook on the given screen + * + * @param pScreen pointer to the screen to register the notify hook into + * @param func pointer to the hook function + * + * When registration fails, the server aborts. + * + * NOTE: only exported for libglamoregl, not supposed to be used by drivers. + **/ +_X_EXPORT +void dixScreenHookClose(ScreenPtr pScreen, + XorgScreenCloseProcPtr func); + +/** + * @brief unregister a screen close notify hook on the given screen + * + * @param pScreen pointer to the screen to unregister the hook from + * @param func pointer to the hook function + * @param arg opaque pointer passed to the destructor + * + * @see dixScreenHookClose + * + * Unregister a screen close notify hook registered via @ref dixScreenHookClose + * + * NOTE: only exported for libglamoregl, not supposed to be used by drivers. + **/ +_X_EXPORT +void dixScreenUnhookClose(ScreenPtr pScreen, + XorgScreenCloseProcPtr func); + #endif /* DIX_SCREEN_HOOKS_H */ diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c index fe734677b..8b499041b 100644 --- a/hw/xfree86/common/xf86platformBus.c +++ b/hw/xfree86/common/xf86platformBus.c @@ -779,7 +779,7 @@ xf86platformRemoveDevice(int index) scrnum = xf86GPUScreens[i]->confScreen->screennum; - xf86GPUScreens[i]->pScreen->CloseScreen(xf86GPUScreens[i]->pScreen); + dixScreenRaiseClose(xf86GPUScreens[i]->pScreen); RemoveGPUScreen(xf86GPUScreens[i]->pScreen); xf86DeleteScreen(xf86GPUScreens[i]); diff --git a/include/scrnintstr.h b/include/scrnintstr.h index 9b7fe73fd..a0fea9262 100644 --- a/include/scrnintstr.h +++ b/include/scrnintstr.h @@ -675,6 +675,10 @@ typedef struct _Screen { /* additional window position notify hooks (replaces wrapping PositionWindow) should NOT be touched outside of DIX core */ CallbackListPtr hookWindowPosition; + + /* additional screen close notify hooks (replaces wrapping CloseScreen) + should NOT be touched outside of DIX core */ + CallbackListPtr hookClose; } ScreenRec; static inline RegionPtr diff --git a/include/xorg-server.h.meson.in b/include/xorg-server.h.meson.in index 58bada923..179e31a31 100644 --- a/include/xorg-server.h.meson.in +++ b/include/xorg-server.h.meson.in @@ -217,5 +217,6 @@ /* announce server API features */ #define XORG_API_DIX_SCREEN_HOOK_WINDOW_DESTROY 1 #define XORG_API_DIX_SCREEN_HOOK_WINDOW_POSITION 1 +#define XORG_API_DIX_SCREEN_HOOK_CLOSE 1 #endif /* _XORG_SERVER_H_ */