📄 liteclue.c
字号:
cw->liteClue.HelpPopDownTime = 0; cw->liteClue.interval_id = (XtIntervalId)0; xcgListInit(&cw->liteClue.widget_list); /* initialize empty list */ compute_font_info(cw); create_GC(cw );}static Boolean setValues( Widget _current, Widget _request, Widget _new, ArgList args, Cardinal * num_args){ XcgLiteClueWidget cw_new = (XcgLiteClueWidget) _new; XcgLiteClueWidget cw_cur = (XcgLiteClueWidget) _current; /* values of cw_new->liteClue.cancelWaitPeriod and cw_new->liteClue.waitPeriod are accepted without checking */ if (cw_new->liteClue.foreground != cw_cur->liteClue.foreground || cw_new->core.background_pixel != cw_cur->core.background_pixel ) { create_GC(cw_new); } return FALSE;}/* ----------------- Event handlers ------------------------*//* At this point the help may be popup */static void timeout_event( XtPointer client_data, XtIntervalId *id){#define OFFSET_X 4 #define OFFSET_Y 4#define BorderPix 2 struct liteClue_context_str * obj = (struct liteClue_context_str *) client_data; XcgLiteClueWidget cw = obj->cw; Position abs_x, abs_y; Dimension clue_width, clue_height; /* variables to retrieve info about the screen size */ Display *display; int screen_num; int display_width; int display_height; Position clue_x, clue_y; XRectangle ink; XRectangle logical; Position w_height; Widget w; if (cw->liteClue.interval_id == (XtIntervalId)0) return; /* timeout was removed but callback happened anyway */ cw->liteClue.interval_id = (XtIntervalId)0; if (obj->sensitive == False) return; w = obj->watched_w; XtVaGetValues(w, XtNheight, &w_height, NULL ); /* position just below the widget */ XtTranslateCoords(w, 0, 0, &abs_x, &abs_y);#if XtSpecificationRelease < 5 || defined(NO_FONT_SET) { int direction_return; int font_ascent_return, font_descent_return; XCharStruct oret; XTextExtents( cw->liteClue.fontset ,obj->text , obj->text_size, &direction_return, &font_ascent_return, &font_descent_return, &oret); logical.width = oret.width; }#else XmbTextExtents(cw->liteClue.fontset, obj->text , obj->text_size ,&ink, &logical);#endif clue_width = 2*BorderPix +logical.width; clue_height = 2*BorderPix + cw->liteClue.font_height; XtResizeWidget((Widget) cw, clue_width, clue_height, cw->core.border_width ); display = XtDisplay(w); screen_num = DefaultScreen(display); display_width = DisplayWidth(display, screen_num); display_height = DisplayHeight(display, screen_num); /* deal with the Y coordinate */ clue_y = abs_y +w_height+OFFSET_Y; /* default position below watched widget */ if (clue_y + clue_height > display_height) /* off bottom of screen ? */ /* then place on top of watched widget */ clue_y = abs_y - clue_height - OFFSET_Y; /* now deal with the X coordinate */ clue_x = abs_x + OFFSET_X; /* default position a little right of watched widget */ if (clue_x < 0 ) /* off left of screen ? */ clue_x = 0; else if (clue_x + clue_width > display_width) /* off right of screen ? */ clue_x = display_width - clue_width - 1; XtMoveWidget((Widget) cw, clue_x, clue_y); XtPopup((Widget) cw, XtGrabNone); cw->liteClue.HelpIsUp = True;#if XtSpecificationRelease < 5 || defined(NO_FONT_SET) XDrawImageString(XtDisplay((Widget) cw), XtWindow((Widget) cw), cw->liteClue.text_GC , BorderPix, BorderPix + cw->liteClue.font_baseline, obj->text, obj->text_size);#else XmbDrawImageString(XtDisplay((Widget) cw), XtWindow((Widget) cw), cw->liteClue.fontset, cw->liteClue.text_GC , BorderPix, BorderPix + cw->liteClue.font_baseline, obj->text, obj->text_size);#undef OFFSET_X#undef OFFSET_Y#endif}/*Pointer enters watched widget, set a timer at which time it willpopup the help*/static void Enter_event(Widget w, XtPointer client_data, XEvent * xevent, Boolean * continue_to_dispatch ){ struct liteClue_context_str * obj = (struct liteClue_context_str *) client_data; XcgLiteClueWidget cw = obj->cw; XEnterWindowEvent * event = & xevent->xcrossing; int current_waitPeriod ; if (obj->sensitive == False || !cw->liteClue.fontset) return; /* check for two enters in a row - happens when widget is exposed under a pop-up */ if (cw->liteClue.interval_id != (XtIntervalId)0) return; if(event->mode != NotifyNormal) return; /* if a help was recently popped down, don't delay in poping up help for next watched widget */ if ((event->time - cw->liteClue.HelpPopDownTime) > cw->liteClue.cancelWaitPeriod ) current_waitPeriod = cw->liteClue.waitPeriod,timeout_event; else current_waitPeriod = 0; cw->liteClue.interval_id = XtAppAddTimeOut( XtWidgetToApplicationContext(w), current_waitPeriod, timeout_event, client_data);}/*Remove timer, if its pending. Then popdown help.*/static void Leave_event(Widget w, XtPointer client_data, XEvent * xevent, Boolean * continue_to_dispatch ){ struct liteClue_context_str * obj = (struct liteClue_context_str *) client_data; XcgLiteClueWidget cw = obj->cw; XEnterWindowEvent * event = & xevent->xcrossing; if (cw->liteClue.interval_id != (XtIntervalId)0) { XtRemoveTimeOut(cw->liteClue.interval_id); cw->liteClue.interval_id= (XtIntervalId)0; } if (obj->sensitive == False) return; if (cw->liteClue.HelpIsUp) { XtPopdown((Widget) cw); cw->liteClue.HelpIsUp = False; cw->liteClue.HelpPopDownTime = event->time; }}/* ---------------- Widget API ---------------------------- *//*;+XcgLiteClueAddWidget -- Add a widget to be watched. LiteClue will be given for this widgetFunc: A widget will be added to the LiteClue watched list. Clues are given for sensitive watched widgets when the pointer enters its window. If the widget is already watched, the passed text replaces its current clue text. If text is null, the widget is still added, if it is not already in the list, but no clue will appear. Text may be specified with XcgLiteClueAddWidget in a subsequent call. When text is null and the widget is already in the list, its text is not changed. When a widget will is added to the watched list, it automatically becomes sensitive. Otherwise, its sensitivity is not changed. A watched widget which is not sensitive retains its context but clues are suppressed. None of this affects the behaviour of the watched widget itself. LiteClue monitors enter and leave events of the watched widget's window passively.Input: w - LiteClue widget watch - the widget to give liteClues for text - pointer to liteClue text. (May be NULL) size - size of text. May be zero in which case a strlen will be done. option - option mask, future use, zero for now.Output: Return: ;-*/void XcgLiteClueAddWidget(Widget w, Widget watch, const char * text, int size, int option ){# define ROUTINE "XcgLiteClueAddWidget" XcgLiteClueWidget cw = (XcgLiteClueWidget) w; struct liteClue_context_str * obj; Boolean exists = False; CheckWidgetClass(ROUTINE); /* make sure we are called with a LiteClue widget */ obj = find_watched_widget(cw, watch); if (obj) { exists = True; if (text) { if(obj->text) XtFree(obj->text); obj->text = NULL; } } else { obj = alloc_link_liteClue_context(cw ); obj->watched_w = watch; } if (text && !(obj->text)) { if (!size) size = strlen(text); obj->text = XtMalloc(size+1); memcpy(obj->text, text, size); obj->text[size] = 0; obj->text_size = size; } if (!exists) /* was created */ { XtAddEventHandler(watch, EnterWindowMask, False, Enter_event, (XtPointer) obj); XtAddEventHandler(watch, LeaveWindowMask|ButtonPressMask, False, Leave_event, (XtPointer) obj); obj->sensitive = True; }# undef ROUTINE}/*;+XcgLiteClueDeleteWidget -- Delete a widget that is watched. Func: A widget is deleted from the watched list and its resources are freed. LiteClue is no longer given for the widget. If the widget is not watched, nothing is done.Input: w - LiteClue widget watch - the widget to deleteOutput: Return: ;-*/void XcgLiteClueDeleteWidget(Widget w, Widget watch){# define ROUTINE "XcgLiteClueDeleteWidget" XcgLiteClueWidget cw = (XcgLiteClueWidget) w; struct liteClue_context_str * obj; CheckWidgetClass(ROUTINE); /* make sure we are called with a LiteClue widget */ obj = find_watched_widget(cw, watch); if (obj) { XtRemoveEventHandler(watch, EnterWindowMask, False, Enter_event, (XtPointer) obj); XtRemoveEventHandler(watch, LeaveWindowMask|ButtonPressMask, False, Leave_event, (XtPointer) obj); if (cw->liteClue.interval_id != (XtIntervalId)0) { XtRemoveTimeOut(cw->liteClue.interval_id); cw->liteClue.interval_id= (XtIntervalId)0; } free_widget_context(cw, obj); }# undef ROUTINE}/*;+XcgLiteClueSetSensitive -- Enable/disable sensitivity for watched widget. Func: When a watched widget is sensitive, a clue is poped up when the pointer enters its window. When a watched widget is insensitive, the widget is retained in the watched list but no clue is poped. The sensitivity of a watched widget relative to clues is set or reset by this function. The Xt sensitivity of the watched widget is not altered by this function.Input: w - LiteClue widget watch - the widget to make sensitive or insensitive or NULL to change all watched widgets sensitive - True or FalseOutput: Return: ;-*/void XcgLiteClueSetSensitive(Widget w, Widget watch, Boolean sensitive){# define ROUTINE "XcgLiteClueSetSensitive" XcgLiteClueWidget cw = (XcgLiteClueWidget) w; struct liteClue_context_str * obj; CheckWidgetClass(ROUTINE); /* make sure we are called with a LiteClue widget */ if (watch) { obj = find_watched_widget(cw, watch); if (obj) { obj->sensitive = sensitive; return; } else return; } /* do them all */ for (obj = (struct liteClue_context_str *) cw->liteClue.widget_list.forw; obj != (struct liteClue_context_str *) & cw->liteClue.widget_list; obj = (struct liteClue_context_str *)obj->next.forw ) { obj->sensitive = sensitive; }# undef ROUTINE}/*;+XcgLiteClueGetSensitive -- Get sensitivity mode for watched widget. Func: When a watched widget is sensitive, a clue is poped up when the pointer enters its window. When a watched widget is insensitive, the widget is retained in the watched list but no clue is poped. The sensitivity state of a watched widget relative to clues is returned by this function. The Xt sensitivity of a widget is a totally independent concept.Input: w - LiteClue widget watch - the widget for which to get sensitivity state. If NULL first watched widget is used. If there are no watched widgets, False is returned.Output: Return: sensitive - True or False;-*/Boolean XcgLiteClueGetSensitive(Widget w, Widget watch){# define ROUTINE "XcgLiteClueGetSensitive" XcgLiteClueWidget cw = (XcgLiteClueWidget) w; struct liteClue_context_str * obj; CheckWidgetClass(ROUTINE); /* make sure we are called with a LiteClue widget */ if (watch) { obj = find_watched_widget(cw, watch); if (obj) return obj->sensitive; else return False; } /* do the first one */ obj = (struct liteClue_context_str *) cw->liteClue.widget_list.forw; if (obj != (struct liteClue_context_str *) & cw->liteClue.widget_list) return obj->sensitive; else return False;# undef ROUTINE}/*;+XcgLiteClueDispatchEvent -- Dispatch event from main X event loopFunc: This function may be used to enable clues for insensitive watched widgets. Normally, XtAppMainLoop (which calls XtDispatchEvent) will not deliver EnterNotify and LeaveNotify events to widgets that are not sensitive (XtSetSensitive). This prevents clues from poping up for these widgets. To bypass this limitation, you can break out XtAppMainLoop and add a call to XcgLiteClueDispatchEvent ass follows: MyXtAppMainLoop(XtAppContext app) { XEvent event; for (;;) { XtAppNextEvent(app, &event); XcgLiteClueDispatchEvent(w, event) ; XtDispatchEvent(&event); } } Input: w - LiteClue widget event - received event, normally from call to XtAppNextEvent.Output: voidReturn: True - event was dispatched to non-sensitive watched widget. False - not a EnterNotify or LeaveNotify event or window in event is not a non-sensitive watched widget.;-*/Boolean XcgLiteClueDispatchEvent(Widget w, XEvent *event){# define ROUTINE "XcgLiteClueDispatchEvent" XcgLiteClueWidget cw = (XcgLiteClueWidget) w; struct liteClue_context_str * obj; Boolean continue_to_dispatch; if (event->type != EnterNotify && event->type != LeaveNotify) return False; CheckWidgetClass(ROUTINE); /* make sure we are called with a LiteClue widget */ /* scan list */ for (obj = (struct liteClue_context_str *) cw->liteClue.widget_list.forw; obj != (struct liteClue_context_str *) & cw->liteClue.widget_list; obj = (struct liteClue_context_str *)obj->next.forw ) { if ((XtWindow(obj->watched_w) != event->xany.window) || (XtIsSensitive(obj->watched_w)) ) continue; /* found one */ if (event->type == EnterNotify ) Enter_event(obj->watched_w, (XtPointer)obj, event, &continue_to_dispatch); else Leave_event(obj->watched_w, (XtPointer)obj, event, &continue_to_dispatch); return True; } return False;# undef ROUTINE}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -