106 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			106 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C
		
	
	
	
| /* SPDX-License-Identifier: MIT OR X11
 | |
|  *
 | |
|  * Copyright © 2024 Enrico Weigelt, metux IT consult <info@metux.net>
 | |
|  */
 | |
| 
 | |
| #include <dix-config.h>
 | |
| 
 | |
| #include "dix/dix_priv.h"
 | |
| #include "include/dix.h"
 | |
| #include "include/os.h"
 | |
| #include "include/scrnintstr.h"
 | |
| #include "include/windowstr.h"
 | |
| 
 | |
| #define ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0]))
 | |
| 
 | |
| #define ARRAY_FOR_EACH(_ARRAY, _WALK) \
 | |
|     for (struct { int idx; typeof(_ARRAY[0])*ptr; } _WALK = { 0, _ARRAY }; _WALK.idx < ARRAY_LENGTH(_ARRAY); _WALK.idx++, _WALK.ptr++)
 | |
| 
 | |
| #define DECLARE_HOOK_LIST(NAME, FIELD) \
 | |
|     void dixScreenHook##NAME(ScreenPtr pScreen, typeof(((ScreenRec){0}).FIELD[0].func) func, void *arg) \
 | |
|     { \
 | |
|         for (int i=0; i<ARRAY_LENGTH(pScreen->FIELD); i++) { \
 | |
|             if (!(pScreen->FIELD[i].func)) { \
 | |
|                 pScreen->FIELD[i].func = func; \
 | |
|                 pScreen->FIELD[i].arg = arg; \
 | |
|                 return; \
 | |
|             } \
 | |
|         } \
 | |
|         FatalError("%s: out of slots", __FUNCTION__); \
 | |
|     } \
 | |
|     \
 | |
|     void dixScreenUnhook##NAME(ScreenPtr pScreen, typeof(((ScreenRec){0}).FIELD[0].func) func, void *arg) \
 | |
|     { \
 | |
|         for (int i=0; i<ARRAY_LENGTH(pScreen->FIELD); i++) { \
 | |
|             if ((pScreen->FIELD[i].func == func) && (pScreen->FIELD[i].arg == arg)) { \
 | |
|                 pScreen->FIELD[i].func = NULL; \
 | |
|                 pScreen->FIELD[i].arg = NULL; \
 | |
|                 return; \
 | |
|             } \
 | |
|         } \
 | |
|     }
 | |
| 
 | |
| DECLARE_HOOK_LIST(WindowDestroy, _notify_window_destroy)
 | |
| DECLARE_HOOK_LIST(WindowPosition, _notify_window_position)
 | |
| DECLARE_HOOK_LIST(Close, _notify_screen_close)
 | |
| DECLARE_HOOK_LIST(PixmapDestroy, _notify_pixmap_destroy)
 | |
| 
 | |
| int dixScreenRaiseWindowDestroy(WindowPtr pWin)
 | |
| {
 | |
|     if (!pWin)
 | |
|         return Success;
 | |
| 
 | |
|     ScreenPtr pScreen = pWin->drawable.pScreen;
 | |
| 
 | |
|     ARRAY_FOR_EACH(pScreen->_notify_window_destroy, walk) {
 | |
|         if (walk.ptr->func)
 | |
|             walk.ptr->func(pScreen, pWin, walk.ptr->arg);
 | |
|     }
 | |
|     return (pScreen->DestroyWindow ? (*pScreen->DestroyWindow) (pWin) : Success);
 | |
| }
 | |
| 
 | |
| void dixScreenRaiseWindowPosition(WindowPtr pWin, uint32_t x, uint32_t y)
 | |
| {
 | |
|     if (!pWin)
 | |
|         return;
 | |
| 
 | |
|     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);
 | |
| }
 | |
| 
 | |
| void dixScreenRaiseClose(ScreenPtr pScreen)
 | |
| {
 | |
|     if (!pScreen)
 | |
|         return;
 | |
| 
 | |
|     ARRAY_FOR_EACH(pScreen->_notify_screen_close, walk) {
 | |
|         if (walk.ptr->func)
 | |
|             walk.ptr->func(pScreen, walk.ptr->arg);
 | |
|     }
 | |
| 
 | |
|     if (pScreen->CloseScreen)
 | |
|         (*pScreen->CloseScreen) (pScreen);
 | |
| }
 | |
| 
 | |
| void dixScreenRaisePixmapDestroy(PixmapPtr pPixmap)
 | |
| {
 | |
|     if (!pPixmap)
 | |
|         return;
 | |
| 
 | |
|     ScreenPtr pScreen = pPixmap->drawable.pScreen;
 | |
| 
 | |
|     ARRAY_FOR_EACH(pScreen->_notify_pixmap_destroy, walk) {
 | |
|         if (walk.ptr->func)
 | |
|             walk.ptr->func(pScreen, pPixmap, walk.ptr->arg);
 | |
|     }
 | |
| 
 | |
|     /* we must not call the original ScreenRec->DestroyPixmap() here */
 | |
| }
 |