//================================================================================
// Xe UI toolkit
//
// Widget base classes
//
// AUTHOR:  Gabor Nagy
// DATE:    2025-May-25 22:32:23
//
// Copyright (C) 1996-2026 by Gabor Nagy. All rights reserved.
//===============================================================================
#ifndef _XeCoreP_h
#define _XeCoreP_h

#ifdef EX11
#include <Xe/XeX.h>
#endif

#include <Xe/XeP.h>

#ifdef XeTHREADS
#include <pthread.h>
#endif

#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
extern "C" {
#endif


#ifdef XeTHREADS
	#define XeWidgetCoreThreads  pthread_t  RedrawThread;pthread_mutex_t  Redraw_mutex;EBool  RedrawThreadCreated;
#else
	#define XeWidgetCoreThreads
#endif

// X11-specific fields in the Core Widget
#ifdef EX11
typedef struct XeWidgetX11Data_S  XeWidgetX11Data;
#define XeWidgetCoreX11\
	XeWidgetX11Data*  X;
#else
#define XeWidgetCoreX11
#endif


#ifdef XeOpenGL
typedef struct XeWidgetGLData_S  XeWidgetGLData;

#define XeWidgetCoreGL\
	XeWidgetGLData*  GL
#else
#define XeWidgetCoreGL
#endif

#define XeWindowINPUT     0x01
#define XeWindowDRAWABLE  0x02
#define XeWindowX11       0x10
#define XeWindowOpenGL    0x20
#define XeWindowVulkan    0x40


typedef struct
{
	int16_t  Radius, TopLeftRadius, TopRightRadius, BottomLeftRadius, BottomRightRadius;
} XeCorners;


typedef struct
{
	XeColor   Color;
	EpImage*  Image;
	EBool     Clear;                       // Clear the background first, when redrawing this Widget
	EBool     Gradient;
	float     GradientContrast;
	XeLayer*  BlendingLayers;
	int       BlendLayersMax;              // Only blend up to this many layers when compositing Images (transparent Widgets). The above array is pre-allocated to this count, to minimize malloc/realloc.
	uint16_t  BlendFunction;               // If not 0 (EpSRCxALPHA_plus_DSTxONE_MINUS_ALPHA etc.), and either BackgroundColor or BackgroundImage is specified, XeX_RealizeWithDraw and _XeCore_Redraw will blend the Widget's Image on the background, otherwise it will simply paste the Image
	int       BlurRadius;
} XeBackground;


#define XeWidgetCore\
	XeRectObjCore;\
\
	XeWidget*       Popups;Cardinal  NPopups;    /* List of popups                          */\
	XeEventTable    EventTable;                  /* Private to event dispatcher             */\
	XeTMData        TM;                          /* Translation management                  */\
	XeTranslations  Accelerators;                /* Accelerator (hotkey) translations       */\
	int             StackingPriority;            /* Higher number means Widget is in front of others */\
	EBool           Visible;                     /* Window is mapped and not occluded       */\
	EBool           MappedWhenManaged;           /* Map window when the widget is managed   */\
	uint16_t        WindowTypeFlags;             /* Flags of XeWindowINPUT and XeWindowDRAWABLE. If not 0, this Widget has its own X11 etc. Window. XeWindowINPUT means drawing is done on the Window of closest windowed ancestor, but event handling is done on this Widget's Window */\
                                               /* XeWindowDRAWABLE means the Window may be drawn into. */\
	uint32_t        Realized : 1,                /* Windowless widgets use this flag to tell that they have been realized (there's no window we can check, but we don't want to keep calling realize) */\
	                Mapped : 1,                  /* This is how the mapped status of windowless widgets is tracked                   */\
	                FirstTimeMap : 1,\
	                RealResize : 1,              /* Windowless Widgets are notified of position changes (as well as size changes).   */\
	                                             /* If the size did not change, Xe_SetGeometry() will set this field to FALSE before calling the resize method of a Widget */\
	                ClearCacheDrawable : 1,      /* Clear X.XCachePixmap with the BackgroundColor if there's no CacheImage */\
\
	                MapHandlerAdded : 1,\
	                RealizeHandlerAdded : 1,\
	                ActiveHandlerAdded : 1,\
	                HaveFocus : 1;\
\
	uint8_t         ResizePolicyX, ResizePolicyY;          /* XeSHRINK|XeGROW */\
	uint8_t         SelfResizePolicyX, SelfResizePolicyY;  /* XeSHRINK|XeGROW */\
	uint16_t        RedrawPolicy;                /* Tells the subclass how to redraw itself. XeRedrawALL, etc.*/\
	XeCoord2        InternalSizeMax;             /* This is the max size Composite Widgets should grant themselves from descendant requests, or the max size Core Widgets should allow themseleves to be. -1 means no limit.  */\
\
	XeCorners       Corners;\
\
	XeBackground    Background;\
\
	XeColor         BorderColor;\
	XeColor         ToolTipBackgroundColor;\
	XeColor         ToolTipForegroundColor;\
	XeFontList      ToolTipFontList;\
\
	XeWidget        ChildWithFocus;\
	XeGeneology     FocalPoint;\
	XeServerGrab*   KeyList;\
	XeServerGrab*   PtrList;\
	XeWidget        QueryEventDescendant;\
	int8_t          KeyboardFocus;             /* -1: not set, 0: no focus 1: focus                      */\
\
	EBool           GeometryUpdateEnabled,     /* The application can enable / disable this, so if there are multiple changes, the Widget and its children will only get updated once */\
	                RedrawEnabled;             /* The application can enable / disable this, so if there are multiple changes, the Widget and its children will only get redrawn once */\
\
	EBool           BufferMotionEvents;        /* Collect all motion events from the queue when they are processed, and store their pointer positions in the XeEvent. This allows higher temporal resolution drawing (more sampled points on the curve) with less overhead than processing each, individual event. */\
\
	EpImage*        WindowMaskImage;\
\
	XeStyle*        Style;\
	EpImage*        CacheImage;\
	EListA_s(, XeImageVariant, CacheImageVariants);\
\
	XeDisplay*      DisplayInfo;\
	XeVisual*       Visual;\
	EIndex          D_DrawCount;               /* For debugging */\
	XeWidgetCoreThreads\
\
	XeWidgetCoreX11\
	XeWidgetCoreGL


typedef struct _XeWidget_S
{
	XeWidgetCore;
} XeWidgetRec;


typedef struct
{
#ifdef EX11
	XeXWValueMask         X_ValueMask;
	XSetWindowAttributes  X_Values;
#endif
} XeRealizeCallData;

extern void    _XeX_ComputeWindowAttributes(XeWidget PW, XeRealizeCallData* PCallData);

typedef void   (*XeXRealizeFunc)(XeWidget PWidget, XeRealizeCallData* PCallData);

extern void    XeP_Realize(XeWidget PW, XeRealizeCallData* PCallData);
extern void    XeP_RealizeWithDraw(XeWidget PW, XeRealizeCallData* PCallData,  const EpImage* (*PRedrawFunc)(XeWidget PW, EpImage* PCacheImage));


#define XeCoreClassCore\
	XeRectObjectClassCore;\
	XeXRealizeFunc     Realize;                     /* Create X11, window or GL buffers etc. for the Widget */\
	XeActionList       Actions;Cardinal  NActions;  /* Action name to function table                        */\
	XeEnum             CompressExposure;            /* Compress Expose events for Widget                    */\
	EBool              CompressMotion;              /* Compress MotionNotify events for Widget              */\
	EBool              CompressEnterLeave;          /* Compress enter and leave events                      */\
	EBool              ReceiveVisibilityChange;     /* This class of Widgets should receive VisibilityNotify events  */\
	XeAcceptFocusFunc  AcceptFocusFunc;             /* Keyboard focus accept function                       */\
	String             TMTable                      /* Translation manager state machine                    */\


struct _XeWidgetClass
{
	XeCoreClassCore;
};

externalref XeWidgetClass  _XeCoreWidget_class;

extern void  XeInheritSetValuesAlmost(XeWidget POldW, XeWidget PW, XeWidgetGeometry* PRequestW, XeWidgetGeometry* PReply);
extern EBool XeInheritAcceptFocus(XeWidget PW, ETime* PTime);

extern void  XeInheritResize(XeWidget PWidget);
extern void  XeInheritRealize(XeWidget PWidget, XeRealizeCallData* PCallData);
extern void  XeInheritRedraw(XeWidget PW, XeRedrawEvent* PEvent);

extern void  _Xe_CoreResize(XeWidget PW);
extern void  _XeCore_Redraw(XeWidget PW, XeRedrawEvent* PEvent, const EpImage* (*PRedrawProc)(XeWidget PW, EpImage* PImage), const EBool PRegenerateImageCache);
extern int   _XeCore_DrawBackgroundAndGetBlendMode(XeWidget PW, const int PBorder, const EBool PBorderWillBeDrawnOver,  EpImage* PCacheImage,  uint16_t* PBlendModeP);

#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
} // Close scope of 'extern "C"' declaration
#endif

#endif // __XeCoreP_h
