diff --git a/dix/dix_priv.h b/dix/dix_priv.h index 74579f20b..ed00e4f3a 100644 --- a/dix/dix_priv.h +++ b/dix/dix_priv.h @@ -266,4 +266,16 @@ extern Bool enableBackingStore; */ 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); + #endif /* _XSERVER_DIX_PRIV_H */ diff --git a/dix/screen_hooks.c b/dix/screen_hooks.c index df95c06c4..bdebbd725 100644 --- a/dix/screen_hooks.c +++ b/dix/screen_hooks.c @@ -41,6 +41,7 @@ } DECLARE_HOOK_LIST(WindowDestroy, _notify_window_destroy) +DECLARE_HOOK_LIST(WindowPosition, _notify_window_position) int dixScreenRaiseWindowDestroy(WindowPtr pWin) { @@ -55,3 +56,16 @@ 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; + + ARRAY_FOR_EACH(pScreen->_notify_window_position, walk) { + if (walk.ptr->func) + walk.ptr->func(pScreen, pWin, walk.ptr->arg, x, y); + } + + if (pScreen->PositionWindow) + (*pScreen->PositionWindow) (pWin, x, y); +} diff --git a/dix/window.c b/dix/window.c index 901fcfc77..db413b8ab 100644 --- a/dix/window.c +++ b/dix/window.c @@ -670,7 +670,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); @@ -928,7 +929,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); @@ -1848,12 +1849,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; @@ -1878,7 +1876,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) { @@ -1888,9 +1887,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; @@ -2584,7 +2583,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/dix_screen_hooks.h b/include/dix_screen_hooks.h index a00cd8d8a..f896c21e6 100644 --- a/include/dix_screen_hooks.h +++ b/include/dix_screen_hooks.h @@ -72,4 +72,40 @@ _X_EXPORT void dixScreenUnhookWindowDestroy(ScreenPtr pScreen, XorgWindowDestroyProcPtr func, void *arg); +/* prototype of a window move notification handler */ +typedef void (*XorgWindowPositionProcPtr)(ScreenPtr pScreen, + WindowPtr pWindow, + void *arg, + int32_t x, + int32_t y); + +/** + * @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. + * + **/ +_X_EXPORT void dixScreenHookWindowPosition(ScreenPtr pScreen, + XorgWindowPositionProcPtr func, + void *arg); + +/** + * @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 + **/ +_X_EXPORT void dixScreenUnhookWindowPosition(ScreenPtr pScreen, + XorgWindowPositionProcPtr func, + void *arg); + #endif /* DIX_SCREEN_HOOKS_H */ diff --git a/include/scrnintstr.h b/include/scrnintstr.h index ef76eaa4c..ae4059f93 100644 --- a/include/scrnintstr.h +++ b/include/scrnintstr.h @@ -561,6 +561,10 @@ typedef struct _Screen { should NOT be touched outside of DIX core */ _SCREEN_HOOK_TYPE(_notify_window_destroy, XorgWindowDestroyProcPtr, 8); + /* additional window position notify hooks (replaces wrapping PositionWindow) + should NOT be touched outside of DIX core */ + _SCREEN_HOOK_TYPE(_notify_window_position, XorgWindowPositionProcPtr, 4); + /* Pixmap procedures */ CreatePixmapProcPtr CreatePixmap; 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 a4b97a7b8..4a71d5387 100644 --- a/mi/miwindow.c +++ b/mi/miwindow.c @@ -50,6 +50,7 @@ SOFTWARE. #include #include "dix/cursor_priv.h" +#include "dix/dix_priv.h" #include "dix/input_priv.h" #include "mi/mi_priv.h" @@ -276,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); @@ -446,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);