📄 pw_window.c
字号:
#include <i_pwin.h>#include "guidebug.h"#include <string.h>
/* -------------------------------------------------------------------------- */#define _WINDOW_IS_CLIP_REGION_NON_EMPTY(_win_) \ ((_win_)->clip_reg.regs_num > 0) #define _WINDOW_SET_CLIP_REGION_TO_ALL(_win_) \ IPW_MACRO_START \ if (PW_NULL != (_win_)->clip_reg.regs) \ { \ IPW_CHECK_COND((_win_)->clip_reg.regs_num > 0); \ IPw_RegionFreeList((_win_)->clip_reg.regs); \ } \ (_win_)->clip_reg.regs = IPw_RegionNew(); \ IPW_FAIL((_win_)->clip_reg.regs != PW_NULL, \ ("Out of free regions!")); \ (_win_)->clip_reg.regs_num = 1; \ IPW_RECT_COPY(&(_win_)->clip_reg.regs->area, &(_win_)->area); \ IPW_RECT_COPY(&(_win_)->clip_reg.bounds, &(_win_)->area); \ IPW_MACRO_END #define _WINDOW_SET_CLIP_REGION_TO_EMPTY(_win_) \ IPW_MACRO_START \ if (PW_NULL != (_win_)->clip_reg.regs) \ { \ IPW_CHECK_COND((_win_)->clip_reg.regs_num > 0); \ IPw_RegionFreeList((_win_)->clip_reg.regs); \ } \ (_win_)->clip_reg.regs = PW_NULL; \ (_win_)->clip_reg.regs_num = 0; \ IPW_RECT_EMPTY(&(_win_)->clip_reg.bounds); \ IPW_MACRO_END #define _WINDOW_COPY_CLIP_REGION(_dst_, _src_) \ IPW_MACRO_START \ (_dst_)->regs_num = (_src_)->regs_num; \ (_dst_)->regs = IPw_RegionNewListFromList((_src_), \ &(_dst_)->regs_num, PW_NULL); \ IPW_FAIL((_dst_)->regs_num == (_src_)->regs_num, \ ("Out of free regions!")); \ IPW_RECT_COPY(&(_dst_)->bounds, &(_src_)->bounds); \ IPW_MACRO_END #define _WINDOW_FREE_CLIP_REGION(_creg_) \ IPW_MACRO_START \ if (PW_NULL != (_creg_)->regs) \ { \ IPW_CHECK_COND((_creg_)->regs_num > 0); \ IPw_RegionFreeList((_creg_)->regs); \ } \ IPW_MACRO_END /* -------------------------------------------------------------------------- *//** * Next free client data id. * @see Pw_WindowGetNewClientDataId */ static Pw_Int _cdata_next_id = 1;/* -------------------------------------------------------------------------- *//** * Initializes basic new window attributes. * @param dpy pointer to display of window * @param win pointer to window to create * @return a newly created window (same as @p win) * @internal */ static Pw_Window* _WindowNew(Pw_Display* dpy, Pw_Window* win){ IPW_TRACE_ENTER(WN2); IPW_CHECK_PTR(dpy); IPW_CHECK_PTR(win); IPW_TRACE3(WN2, p, win, win->parent, dpy); /* Quick check for empty window space */ IPW_FAIL(PW_NULL == win->parent, ("dirty or used window space %p", win)); /* Set the display */ win->dpy = dpy; /* Set the window area */ IPW_RECT_EMPTY(&win->area); /* Set other window attributes */ win->parent = PW_NULL; win->children = PW_NULL; win->children_num = 0; win->prev = PW_NULL; win->next = PW_NULL; win->focus_accept = FALSE; win->mapped = FALSE; /* Set window clip region to empty */ win->clip_reg.regs_num = 0; win->clip_reg.regs = PW_NULL; IPW_RECT_EMPTY(&win->clip_reg.bounds); /* Set window callback functions to null */ win->event_cb = PW_NULL; win->repaint_cb = PW_NULL; /* Set client data to null */ win->cdata_id = -1; win->cdata = PW_NULL; IPW_TRACE_EXIT_V(WN2, p, win); return(win);}/** * Adds window @p win to parent window @p parent. * @param win pointer to window * @param parent pointer to parent window * @internal */ static void _WindowAddToParent(Pw_Window* win, Pw_Window* parent){ IPW_TRACE_ENTER(WN2); IPW_CHECK_PTR(win); IPW_CHECK_PTR(parent); IPW_TRACE2(WN2, p, win, parent); IPW_TRACE3(WN1, p, win->next, win->prev, win->parent); IPW_TRACE1(WN1, d, parent->children_num); /* * Window should not be added to another window * if it already has a parent */ IPW_CHECK_COND(PW_NULL == win->parent); /* Increase parent window child count */ parent->children_num++; /* Check if this window is the first child of parent window */ if (PW_NULL == parent->children) { /* First child */ parent->children = win; win->prev = PW_NULL; win->next = PW_NULL; } else { /* Not the first child - add the window on top (start of the list) */ parent->children->prev = win; win->next = parent->children; win->prev = PW_NULL; parent->children = win; } /* Set the window parent pointer */ win->parent = parent; IPW_TRACE3(WN1, p, win->next, win->prev, win->parent); IPW_TRACE1(WN1, d, parent->children_num); IPW_TRACE_EXIT(WN2);}/** * Removes window @p win from parent window. * @param win pointer to window * @internal */ static void _WindowRemoveFromParent(Pw_Window* win){ Pw_Window* cld_win; Pw_Window* pre_win; IPW_TRACE_ENTER(WN2); IPW_CHECK_PTR(win); IPW_TRACE2(WN2, p, win, win->parent); IPW_CHECK_COND(PW_NULL != win->parent); IPW_TRACE1(WN1, d, win->parent->children_num); /* Find previous window of this window in its parent child list */ cld_win = win->parent->children; pre_win = PW_NULL; while ((cld_win != win) && (PW_NULL != cld_win)) { pre_win = cld_win; cld_win = cld_win->next; } IPW_CHECK_COND(PW_NULL != cld_win); IPW_TRACE2(WN1, p, pre_win, cld_win->next); if (PW_NULL == pre_win) { /* * This window is the first window in its parent * child list - just correct parents first child pointer */ win->parent->children = cld_win->next; if (PW_NULL != cld_win->next) cld_win->next->prev = PW_NULL; } else { /* * This window is not the first window in its parent * child list - corrent previous window next pointer * to point to this window next window */ pre_win->next = cld_win->next; if (PW_NULL != cld_win->next) cld_win->next->prev = pre_win; } /* Decrease this window parent child count */ win->parent->children_num--; IPW_TRACE1(WN1, d, win->parent->children_num); /* Set window parent to NULL */ win->parent = PW_NULL; IPW_TRACE_EXIT(WN2);}/** * Sets the clip region of all of window @p win children to empty (invisible). * @param win pointer to window * @internal */ static void _WindowSetChildrenClipRegionToEmpty(Pw_Window* win){ Pw_Window* cld_win; IPW_TRACE_ENTER(WN2); IPW_CHECK_PTR(win); IPW_TRACE2(WN1, p, win, win->children); /* * Set the clip region of current child window to empty and * then call this function recursively for all of current * child window children */ cld_win = win->children; while (PW_NULL != cld_win) { IPW_TRACE1(WN1, p, cld_win); _WINDOW_SET_CLIP_REGION_TO_EMPTY(cld_win); _WindowSetChildrenClipRegionToEmpty(cld_win); cld_win = cld_win->next; } IPW_TRACE_EXIT(WN2);}/** * Updates window @p win clip region and the clip region of its children. * @param win pointer to window * @internal */ static void _WindowUpdateClipRegion(Pw_Window* win){ Pw_Window* par_win; Pw_Window* cur_win; Pw_Window* tmp_win; Pw_RegionList* clip_reg; Pw_Region* reg; IPW_TRACE_ENTER(WN2); IPW_CHECK_PTR(win); /* If this window is not mapped we have nothing to do */ if (!win->mapped) { IPW_TRACE_EXIT(WN2); return; } /* * Start with the whole window area and then remove the obscured parts */
_WINDOW_SET_CLIP_REGION_TO_ALL(win); /* Set the ptr to this window clip region */ clip_reg = &win->clip_reg; /* * Find the visible region of this window trough all of * its parents (up to the root window wich parent is NULL) */ par_win = win->parent; while (PW_NULL != par_win) { IPW_TRACE_RECT2(WN1, &par_win->area, &clip_reg->regs->area); /* Calculate the visible window part trough the current parent */ IPw_RectIntersect(&clip_reg->regs->area, &par_win->area); IPW_TRACE_RECT(WN1, &clip_reg->regs->area); if (!IPW_RECT_IS_VALID(&clip_reg->regs->area)) { /* * This window is not visible at all (and all * of its children are not visible as well) */ _WINDOW_SET_CLIP_REGION_TO_EMPTY(win); _WindowSetChildrenClipRegionToEmpty(win); IPW_TRACE_EXIT(WN2); return; } par_win = par_win->parent; } /* * Remove parts wich are obscured by windows on top of this window - this * are the children of this window parent that are on top of this window * and the children of this window parent parent that are on top of this * window parent, and so on until we reach the root window */ tmp_win = win; par_win = win->parent; while (PW_NULL != par_win) { IPW_TRACE1(WN1, p, par_win); /* * Exclude window area of windows on top of this * window or on top of one of this window parents - * we stop when we reach tmp_win (in the first loop * tmp_win is this window and in the following loop its * one of this window parents) */ cur_win = par_win->children; /* Child window on top */ while (cur_win != tmp_win) { IPW_TRACE2M(WN1, p, cur_win, d, cur_win->mapped); /* If window is not mapped it can't obscure anything */ if (cur_win->mapped) { /* * Exclude current window area from this window and check * if the number of clip rectangles has reached the limit */ if (!IPw_RectExcludeFromRegionList(&(cur_win->area), clip_reg)) { Pw_Int fcnt; /* * Too many clip rectangles - just make this window * and all of its children invisible */ IPW_WARN(FALSE, ("Out of free regions for window (%p)!", win)); IPW_TRACE1(WN1, d, win->clip_reg.regs_num); _WINDOW_SET_CLIP_REGION_TO_EMPTY(win); _WindowSetChildrenClipRegionToEmpty(win); fcnt = IPw_RegionGetFreeCnt(); IPW_TRACE1(WN1, d, fcnt); IPW_TRACE_EXIT(WN2); return; } IPW_TRACE1(WN1, d, clip_reg->regs_num); } cur_win = cur_win->next; } tmp_win = par_win; par_win = par_win->parent; } /* Calculate the bounds of this window clip region */ if (PW_NULL != clip_reg->regs) { reg = clip_reg->regs; IPW_RECT_COPY(&clip_reg->bounds, ®->area); IPW_TRACE_RECT(WN1, ®->area); reg = reg->next; while (PW_NULL != reg) { IPW_TRACE_RECT(WN1, ®->area); IPw_RectUnionize(&clip_reg->bounds, ®->area); reg = reg->next; } } else { IPW_RECT_EMPTY(&clip_reg->bounds); } IPW_TRACE_RECT(WN1, &clip_reg->bounds); IPW_CHECK_RLIST_HARD(&win->clip_reg); /* Update the clip region for all children of this window */ cur_win = win->children; while (PW_NULL != cur_win) { _WindowUpdateClipRegion(cur_win); cur_win = cur_win->next; } IPW_TRACE_EXIT(WN2);}/** * Creates window @p win graphic context @p gc with clip region @p clip. * @param win pointer to window * @param clip pointer to clip rectangle * @param gc pointer to gc * @return true if gc applays to a visible region * @internal */ static Pw_Bool _WindowCreateGC(Pw_Window* win, Pw_Rectangle* clip, Pw_GC* gc){ IPW_TRACE_ENTER(WN2); IPW_CHECK_PTR2(win, gc); IPW_TRACE3(WN1, p, win, clip, gc); gc->d.type = Pw_DrawableWindowType; /* Set the type */ gc->d.comp.window = win; /* Set the window */ gc->d.lld = win->dpy->dd->lld; /* Set low level drawing routines */ gc->xoff = win->area.x; /* Set the x offset (origin) */ gc->yoff = win->area.y; /* Set the y offset (origin) */ gc->color = pw_black_pixel; /* Set the color */
gc->font = PW_NULL; /* Set the font REMIND: default font?!? */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -