//================================================================================
// Xe UI toolkit
//
// Widget base classes
//
// AUTHOR:  Gabor Nagy
// DATE:    2026-Jun-10 22:44:17
//
// 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;

// 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.
	int       BlendLayersMax;

// 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
	uint16_t  BlendFunction;

	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   */\
\
/* 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 the closest */\
/* windowed ancestor, but event handling is done on this Widget's Window */\
	uint16_t        WindowTypeFlags;\
                                               /* XeWindowDRAWABLE means the Window may be drawn into. */\
\
/* 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) */\
	uint32_t        Realized : 1,\
	                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.*/\
\
/* 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.  */\
	XeCoord2        InternalSizeMax;\
\
	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 */\
\
/* 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. */\
	EBool           BufferMotionEvents;\
\
	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
