diff --git a/dix/dix_priv.h b/dix/dix_priv.h index a07889284..8e6e406d6 100644 --- a/dix/dix_priv.h +++ b/dix/dix_priv.h @@ -283,6 +283,18 @@ void dixFreeScreen(ScreenPtr pScreen); */ int dixScreenRaiseWindowDestroy(WindowPtr pWin); +/* + * @brief call screen's window position notification hooks + * @see dixScreenHookWindowPosition + * @param pWin the window to notify on + * + * Call the pluggable window position hooks that extensions might have registered on + * the screen, and finally call ScreenRec's PositionWindow proc. + * + * Should only be called by DIX itself. + */ +void dixScreenRaiseWindowPosition(WindowPtr pWin, uint32_t x, uint32_t y); + /* * @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 9bdd92b76..4458c7250 100644 --- a/dix/screen.c +++ b/dix/screen.c @@ -21,5 +21,6 @@ void dixFreeScreen(ScreenPtr pScreen) pScreen->CloseScreen(pScreen); dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN); DeleteCallbackList(&pScreen->hookWindowDestroy); + DeleteCallbackList(&pScreen->hookWindowPosition); free(pScreen); } diff --git a/dix/screen_hooks.c b/dix/screen_hooks.c index 6e56e00f1..1bfff195d 100644 --- a/dix/screen_hooks.c +++ b/dix/screen_hooks.c @@ -24,6 +24,7 @@ } DECLARE_HOOK_PROC(WindowDestroy, hookWindowDestroy, XorgScreenWindowDestroyProcPtr); +DECLARE_HOOK_PROC(WindowPosition, hookWindowPosition, XorgScreenWindowPositionProcPtr); int dixScreenRaiseWindowDestroy(WindowPtr pWin) { @@ -36,3 +37,19 @@ int dixScreenRaiseWindowDestroy(WindowPtr pWin) return (pScreen->DestroyWindow ? pScreen->DestroyWindow(pWin) : Success); } + +void dixScreenRaiseWindowPosition(WindowPtr pWin, uint32_t x, uint32_t y) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + XorgScreenWindowPositionParamRec param = { + .window = pWin, + .x = x, + .y = y, + }; + + CallCallbacks(&pScreen->hookWindowPosition, ¶m); + + if (pScreen->PositionWindow) + pScreen->PositionWindow(pWin, x, y); +} diff --git a/dix/screen_hooks_priv.h b/dix/screen_hooks_priv.h index ce40734b5..012adec15 100644 --- a/dix/screen_hooks_priv.h +++ b/dix/screen_hooks_priv.h @@ -71,4 +71,42 @@ void dixScreenHookWindowDestroy(ScreenPtr pScreen, void dixScreenUnhookWindowDestroy(ScreenPtr pScreen, XorgScreenWindowDestroyProcPtr func); +typedef struct { + WindowPtr window; + int32_t x; + int32_t y; +} XorgScreenWindowPositionParamRec; + +/* prototype of a window move notification handler */ +typedef void (*XorgScreenWindowPositionProcPtr)(CallbackListPtr *pcbl, + ScreenPtr pScreen, + XorgScreenWindowPositionParamRec *param); + +/** + * @brief register a position notify hook on the given screen + * + * @param pScreen pointer to the screen to register the notify hook into + * @param func pointer to the window hook function + * @param arg opaque pointer passed to the hook + * + * When registration fails, the server aborts. + * + **/ +void dixScreenHookWindowPosition(ScreenPtr pScreen, + XorgScreenWindowPositionProcPtr func); + +/** + * @brief unregister a window position 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 dixScreenHookWindowPosition + * + * Unregister a window position notify hook registered via @ref dixScreenHookWindowPosition + **/ +void dixScreenUnhookWindowPosition(ScreenPtr pScreen, + XorgScreenWindowPositionProcPtr func); + #endif /* DIX_SCREEN_HOOKS_H */ diff --git a/dix/window.c b/dix/window.c index de6476459..693bb736e 100644 --- a/dix/window.c +++ b/dix/window.c @@ -668,7 +668,8 @@ InitRootWindow(WindowPtr pWin) if (!(*pScreen->CreateWindow) (pWin)) return; /* XXX */ - (*pScreen->PositionWindow) (pWin, 0, 0); + + dixScreenRaiseWindowPosition(pWin, 0, 0); pWin->cursorIsNone = FALSE; pWin->optional->cursor = RefCursor(rootCursor); @@ -926,7 +927,7 @@ CreateWindow(Window wid, WindowPtr pParent, int x, int y, unsigned w, return NullWindow; } /* We SHOULD check for an error value here XXX */ - (*pScreen->PositionWindow) (pWin, pWin->drawable.x, pWin->drawable.y); + dixScreenRaiseWindowPosition(pWin, pWin->drawable.x, pWin->drawable.y); if (!(vmask & CWEventMask)) RecalculateDeliverableEvents(pWin); @@ -1846,12 +1847,9 @@ GravityTranslate(int x, int y, int oldx, int oldy, void ResizeChildrenWinSize(WindowPtr pWin, int dx, int dy, int dw, int dh) { - ScreenPtr pScreen; WindowPtr pSib, pChild; Bool resized = (dw || dh); - pScreen = pWin->drawable.pScreen; - for (pSib = pWin->firstChild; pSib; pSib = pSib->nextSib) { if (resized && (pSib->winGravity > NorthWestGravity)) { int cwsx, cwsy; @@ -1876,7 +1874,8 @@ ResizeChildrenWinSize(WindowPtr pWin, int dx, int dy, int dw, int dh) pSib->drawable.y = pWin->drawable.y + pSib->origin.y; SetWinSize(pSib); SetBorderSize(pSib); - (*pScreen->PositionWindow) (pSib, pSib->drawable.x, pSib->drawable.y); + + dixScreenRaiseWindowPosition(pSib, pSib->drawable.x, pSib->drawable.y); if ((pChild = pSib->firstChild)) { while (1) { @@ -1886,9 +1885,9 @@ ResizeChildrenWinSize(WindowPtr pWin, int dx, int dy, int dw, int dh) pChild->origin.y; SetWinSize(pChild); SetBorderSize(pChild); - (*pScreen->PositionWindow) (pChild, - pChild->drawable.x, - pChild->drawable.y); + dixScreenRaiseWindowPosition(pChild, + pChild->drawable.x, + pChild->drawable.y); if (pChild->firstChild) { pChild = pChild->firstChild; continue; @@ -2582,7 +2581,8 @@ ReparentWindow(WindowPtr pWin, WindowPtr pParent, if (pScreen->ReparentWindow) (*pScreen->ReparentWindow) (pWin, pPriorParent); - (*pScreen->PositionWindow) (pWin, pWin->drawable.x, pWin->drawable.y); + + dixScreenRaiseWindowPosition(pWin, pWin->drawable.x, pWin->drawable.y); ResizeChildrenWinSize(pWin, 0, 0, 0, 0); CheckWindowOptionalNeed(pWin); diff --git a/include/scrnintstr.h b/include/scrnintstr.h index 73adbe375..9b7fe73fd 100644 --- a/include/scrnintstr.h +++ b/include/scrnintstr.h @@ -671,6 +671,10 @@ typedef struct _Screen { /* additional window destructors (replaces wrapping DestroyWindow). should NOT be touched outside of DIX core */ CallbackListPtr hookWindowDestroy; + + /* additional window position notify hooks (replaces wrapping PositionWindow) + should NOT be touched outside of DIX core */ + CallbackListPtr hookWindowPosition; } ScreenRec; static inline RegionPtr diff --git a/include/xorg-server.h.meson.in b/include/xorg-server.h.meson.in index 392d8ede5..58bada923 100644 --- a/include/xorg-server.h.meson.in +++ b/include/xorg-server.h.meson.in @@ -216,5 +216,6 @@ /* announce server API features */ #define XORG_API_DIX_SCREEN_HOOK_WINDOW_DESTROY 1 +#define XORG_API_DIX_SCREEN_HOOK_WINDOW_POSITION 1 #endif /* _XORG_SERVER_H_ */ diff --git a/mi/miwindow.c b/mi/miwindow.c index 4badaf471..4a71d5387 100644 --- a/mi/miwindow.c +++ b/mi/miwindow.c @@ -277,7 +277,7 @@ miMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pNextSib, VTKind kind) SetWinSize(pWin); SetBorderSize(pWin); - (*pScreen->PositionWindow) (pWin, x, y); + dixScreenRaiseWindowPosition(pWin, x, y); windowToValidate = MoveWindowInStack(pWin, pNextSib); @@ -447,7 +447,7 @@ miResizeWindow(WindowPtr pWin, int x, int y, unsigned int w, unsigned int h, ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh); /* let the hardware adjust background and border pixmaps, if any */ - (*pScreen->PositionWindow) (pWin, x, y); + dixScreenRaiseWindowPosition(pWin, x, y); pFirstChange = MoveWindowInStack(pWin, pSib);