2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
25 * $XConsortium: ui_util.c /main/3 1995/11/06 17:56:30 rswiston $
27 * @(#)ui_util.c 1.38 14 Feb 1994 cde_app_builder/src/ab
29 * RESTRICTED CONFIDENTIAL INFORMATION:
31 * The information in this document is subject to special
32 * restrictions in a confidential disclosure agreement between
33 * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
34 * document outside HP, IBM, Sun, USL, SCO, or Univel without
35 * Sun's specific written approval. This document and all copies
36 * and derivative works thereof must be returned or destroyed at
39 * Copyright 1993 Sun Microsystems, Inc. All rights reserved.
45 ***********************************************************************
46 * ui_util.c - User-Interface support functions
49 ***********************************************************************
51 #ifndef _POSIX_SOURCE /* POSIX guarantees portability of time functions */
52 #define _POSIX_SOURCE 1
59 #include <X11/Intrinsic.h>
60 #include <X11/Composite.h>
61 #include <X11/Shell.h>
62 #include <X11/cursorfont.h>
65 #include <Xm/Protocols.h>
66 #include <Xm/CascadeB.h>
67 #include <Xm/DialogS.h>
70 #include <Xm/ScrolledW.h>
71 #include <Xm/RowColumn.h>
74 #include <Xm/MessageB.h>
77 #include <Dt/SpinBox.h>
78 #include <Dt/TermPrim.h>
80 #include <ab_private/XmAll.h>
81 #include <ab_private/x_util.h>
82 #include <ab_private/ui_util.h>
83 #include <ab_private/objxm.h>
84 #include <ab_private/ab.h>
85 #include <Dt/xpm.h> /* will this be in include/Dt? */
86 #include "dtbuilder.h"
87 #include "dtb_utils.h"
89 extern Widget AB_toplevel;
97 time_t last_expose_ticks;
100 } SyncDataRec, *SyncData;
103 /*************************************************************************
105 ** Private Function Declarations **
107 **************************************************************************/
108 static void init_obj_pixmaps();
110 static void rubberband_finish(
113 XtPointer client_data
116 static void rubberband_release(
118 XtPointer client_data,
120 Boolean *cont_dispatch
123 static void rubberband_draw(
126 XtPointer client_data
129 /*************************************************************************
133 **************************************************************************/
135 static const long sync_notify_value = (long)0x45a55a54;
139 * Array that maps from:
140 * (obj type, obj subtype) -> pixmap
141 * It contains the data that will be used to create the pixmap.
143 static UiObjPixmap object_pixmaps[] =
145 /* { (AB_OBJECT_TYPE), (int), (char *), (Pixmap), u_int, u_int } */
146 {AB_TYPE_MODULE, AB_NO_SUBTYPE, "DtABmdl", (Pixmap)NULL, 0, 0},
148 {AB_TYPE_BASE_WINDOW, AB_NO_SUBTYPE, "DtABbw2", (Pixmap)NULL, 0, 0},
150 {AB_TYPE_DIALOG, AB_NO_SUBTYPE, "DtABpuw2", (Pixmap)NULL, 0, 0},
152 {AB_TYPE_FILE_CHOOSER, AB_NO_SUBTYPE, "DtABfsb2", (Pixmap)NULL, 0, 0},
154 {AB_TYPE_CONTAINER, AB_CONT_BUTTON_PANEL, "DtABcnt2", (Pixmap)NULL, 0, 0},
155 {AB_TYPE_CONTAINER, AB_CONT_ABSOLUTE, "DtABcnt2", (Pixmap)NULL, 0, 0},
156 {AB_TYPE_CONTAINER, AB_CONT_RELATIVE, "DtABcnt2", (Pixmap)NULL, 0, 0},
157 {AB_TYPE_CONTAINER, AB_CONT_PANED, "DtABpnw", (Pixmap)NULL, 0, 0},
158 {AB_TYPE_CONTAINER, AB_CONT_MENU_BAR, "DtABmbr", (Pixmap)NULL, 0, 0},
159 {AB_TYPE_CONTAINER, AB_CONT_TOOL_BAR, "DtABcnt2", (Pixmap)NULL, 0, 0},
160 {AB_TYPE_CONTAINER, AB_CONT_FOOTER, "DtABcnt2", (Pixmap)NULL, 0, 0},
161 {AB_TYPE_CONTAINER, AB_CONT_GROUP, "DtABgrp", (Pixmap)NULL, 0, 0},
163 {AB_TYPE_DRAWING_AREA, AB_NO_SUBTYPE, "DtABdrw2", (Pixmap)NULL, 0, 0},
165 {AB_TYPE_TEXT_PANE, AB_NO_SUBTYPE, "DtABtxp2", (Pixmap)NULL, 0, 0},
167 {AB_TYPE_BUTTON, AB_BUT_PUSH, "DtABbtn", (Pixmap)NULL, 0, 0},
168 {AB_TYPE_BUTTON, AB_BUT_DRAWN, "DtABbtn", (Pixmap)NULL, 0, 0},
169 {AB_TYPE_BUTTON, AB_BUT_MENU, "DtABmbt", (Pixmap)NULL, 0, 0},
171 {AB_TYPE_LIST, AB_NO_SUBTYPE, "DtABlst", (Pixmap)NULL, 0, 0},
173 {AB_TYPE_CHOICE, AB_CHOICE_OPTION_MENU, "DtABopm", (Pixmap)NULL, 0, 0},
174 {AB_TYPE_CHOICE, AB_CHOICE_EXCLUSIVE, "DtABrad", (Pixmap)NULL, 0, 0},
175 {AB_TYPE_CHOICE, AB_CHOICE_NONEXCLUSIVE, "DtABchk", (Pixmap)NULL, 0, 0},
177 {AB_TYPE_ITEM, AB_ITEM_FOR_MENU, "DtABcas", (Pixmap)NULL, 0, 0},
178 {AB_TYPE_ITEM, AB_ITEM_FOR_MENUBAR, "DtABcas", (Pixmap)NULL, 0, 0},
179 {AB_TYPE_ITEM, AB_ITEM_FOR_CHOICE, "DtABitm", (Pixmap)NULL, 0, 0},
180 {AB_TYPE_ITEM, AB_ITEM_FOR_LIST, "DtABitm", (Pixmap)NULL, 0, 0},
181 {AB_TYPE_ITEM, AB_ITEM_FOR_COMBO_BOX, "DtABitm", (Pixmap)NULL, 0, 0},
182 {AB_TYPE_ITEM, AB_ITEM_FOR_SPIN_BOX, "DtABitm", (Pixmap)NULL, 0, 0},
184 {AB_TYPE_TEXT_FIELD, AB_NO_SUBTYPE, "DtABtxf", (Pixmap)NULL, 0, 0},
186 {AB_TYPE_MENU, AB_MENU_PULLDOWN, "DtABpum", (Pixmap)NULL, 0, 0},
187 {AB_TYPE_SCALE, AB_SCALE_SCALE, "DtABsld", (Pixmap)NULL, 0, 0},
188 {AB_TYPE_SCALE, AB_SCALE_GAUGE, "DtABgau", (Pixmap)NULL, 0, 0},
189 {AB_TYPE_COMBO_BOX, AB_NO_SUBTYPE, "DtABcmb", (Pixmap)NULL, 0, 0},
190 {AB_TYPE_SPIN_BOX, AB_NO_SUBTYPE, "DtABspb", (Pixmap)NULL, 0, 0},
191 {AB_TYPE_TERM_PANE, AB_NO_SUBTYPE, "DtABtmp2", (Pixmap)NULL, 0, 0},
192 {AB_TYPE_SEPARATOR, AB_NO_SUBTYPE, "DtABsep", (Pixmap)NULL, 0, 0},
193 {AB_TYPE_LABEL, AB_NO_SUBTYPE, "DtABlbl", (Pixmap)NULL, 0, 0},
195 {AB_TYPE_MESSAGE, AB_MSG_ERROR, "DtABmbx", (Pixmap)NULL, 0, 0},
196 {AB_TYPE_MESSAGE, AB_MSG_INFORMATION, "DtABmbx", (Pixmap)NULL, 0, 0},
197 {AB_TYPE_MESSAGE, AB_MSG_QUESTION, "DtABmbx", (Pixmap)NULL, 0, 0},
198 {AB_TYPE_MESSAGE, AB_MSG_WARNING, "DtABmbx", (Pixmap)NULL, 0, 0},
199 {AB_TYPE_MESSAGE, AB_MSG_WORKING, "DtABmbx", (Pixmap)NULL, 0, 0},
201 {AB_TYPE_LAYERS, AB_NO_SUBTYPE, "DtABlyr", (Pixmap)NULL, 0, 0},
203 /* The last entry has to be this !!*/
204 {AB_TYPE_UNKNOWN, AB_NO_SUBTYPE, (char *)NULL, (Pixmap)NULL, 0, 0},
210 static Pixmap default_pixmap = NULL;
211 static unsigned int default_pixmap_width = 0;
212 static unsigned int default_pixmap_height = 0;
215 * State variables for rubber banding
217 static Boolean rband_in_progress= False;
218 static Boolean just_rbanded = False;
219 static XRectangle rb_rect;
220 static Widget rb_widget = NULL;
221 static BOOL rb_first_time = TRUE;
222 static UiRubberBandFunc rubberband_func = NULL;
224 /*************************************************************************
226 ** Function Definitions **
228 **************************************************************************/
239 p_shell = ui_get_ancestor_shell(widget);
241 if (XtIsRealized(p_shell))
242 XRaiseWindow(XtDisplay(p_shell),XtWindow(p_shell));
244 if (util_get_verbosity() > 0)
245 fprintf(stderr,"ui_win_front: widget not realized\n");
259 shell = ui_get_ancestor_shell(widget);
262 XtPopup(shell, grab_kind);
268 ui_win_set_resizable(
280 shell = ui_get_ancestor_shell(widget);
283 XmNmwmDecorations, &decor,
284 XmNmwmFunctions, &func,
287 if (func & MWM_FUNC_ALL)
289 new_func |= MWM_FUNC_ALL;
291 new_func |= MWM_FUNC_RESIZE;
296 if (resizable && !(func & MWM_FUNC_RESIZE))
297 new_func |= MWM_FUNC_RESIZE;
298 else if (!resizable && (func & MWM_FUNC_RESIZE))
299 new_func &= ~MWM_FUNC_RESIZE;
302 if (decor & MWM_DECOR_ALL)
304 new_decor |= MWM_DECOR_ALL;
306 new_decor |= MWM_DECOR_RESIZEH;
311 if (resizable && !(decor & MWM_DECOR_RESIZEH))
312 new_decor |= MWM_DECOR_RESIZEH;
313 else if (!resizable && (decor & MWM_DECOR_RESIZEH))
314 new_decor &= ~MWM_DECOR_RESIZEH;
317 if (new_func != func || new_decor != decor)
319 /* If requested, unmap & remap the window.
320 * Unfortunately, this is the only way to get the window
321 * manager to change the decorations for an already mapped
328 XmNmwmDecorations, new_decor,
329 XmNmwmFunctions, new_func,
333 XtPopup(shell, XtGrabNone);
345 XmNvalue, (XtArgVal)(valuestr? valuestr : ""),
346 XmNcursorPosition, (XtArgVal)valuestr? strlen(valuestr) : 0,
358 if (XtIsSubclass(field, xmTextFieldWidgetClass))
359 string = XmTextFieldGetString(field);
360 else if (XtIsSubclass(field, xmTextWidgetClass))
361 string = XmTextGetString(field);
363 return((STRING)string);
367 ui_field_select_string(
372 STRING valuestr = NULL;
374 valuestr = ui_field_get_string(field);
376 if (XtIsSubclass(field, xmTextFieldWidgetClass))
377 XmTextFieldSetSelection(field, 0, strlen(valuestr), CurrentTime);
378 else if (XtIsSubclass(field, xmTextWidgetClass))
379 XmTextSetSelection(field, 0, strlen(valuestr), CurrentTime);
382 XmProcessTraversal(field, XmTRAVERSE_CURRENT);
388 ui_field_set_editable(
394 XmNeditable, editable,
395 XmNcursorPositionVisible, editable,
405 XtSetSensitive(widget, (Boolean)state);
407 if (XtIsComposite(widget))
409 int i, num_children = 0;
410 WidgetList children = NULL;
412 XtVaGetValues(widget,
413 XmNnumChildren, &num_children,
414 XmNchildren, &children,
417 for (i = 0; i < num_children; i++)
419 int c = 0, num_children_children = 0;
420 WidgetList children_children = NULL;
422 XtSetSensitive(children[i], (Boolean)state);
424 /* REMIND: Hack to get scrolling list to grey out */
426 XtVaGetValues(children[i],
427 XmNnumChildren, &num_children_children,
428 XmNchildren, &children_children,
431 if (num_children_children > 0)
433 for (c = 0; c < num_children_children; c++)
434 XtSetSensitive(children_children[c], (Boolean)state);
446 if (viz == TRUE && !XtIsManaged(widget))
447 XtManageChild(widget);
449 else if (viz == FALSE && XtIsManaged(widget))
450 XtUnmanageChild(widget);
462 xmlabel = XmStringCreateLocalized(string);
464 XtVaSetValues(widget, XmNlabelString, xmlabel, NULL);
466 XmStringFree(xmlabel);
475 Pixmap labelPixmap = NULL;
476 Pixmap labelInsensitivePixmap = NULL;
478 XtVaGetValues(widget,
479 XmNlabelPixmap, &labelPixmap,
480 XmNlabelInsensitivePixmap, &labelInsensitivePixmap,
483 if (dtb_set_label_from_image_file(widget, fileName) < 0)
486 /* sucess, destroy the old pixmaps */
488 XmDestroyPixmap(XtScreen(widget), labelPixmap);
490 if (labelInsensitivePixmap)
491 XmDestroyPixmap(XtScreen(widget), labelInsensitivePixmap);
496 ui_get_ancestor_shell(
500 Widget shell = widget;
502 while(shell && !XtIsSubclass(shell, shellWidgetClass))
503 shell = XtParent(shell);
510 ui_get_ancestor_dialog(
514 Widget dialog = widget;
516 while(dialog && !XtIsSubclass(XtParent(dialog), shellWidgetClass))
517 dialog = XtParent(dialog);
542 XtSetArg(args[n], XmNpacking, XmPACK_COLUMN); n++;
543 XtSetArg(args[n], XmNnumColumns, num_columns); n++;
545 if (menu_type == XmMENU_PULLDOWN)
546 menu = XmCreatePulldownMenu(parent, "pulldown_menu", args, n);
549 XtSetArg(args[n], XmNwhichButton, AB_BMenu); n++;
550 menu = XmCreatePopupMenu(parent, "popup_menu", args, n);
553 if (menu_type == XmMENU_PULLDOWN)
555 cascade = XtVaCreateManagedWidget(menu_name,
556 xmCascadeButtonWidgetClass, parent,
562 xmlabel = XmStringCreateLocalized(menu_title);
563 XtVaSetValues(cascade, XmNlabelString, xmlabel, NULL);
564 XmStringFree(xmlabel);
568 for (i = 0; menu_items[i].label != NULL; i++)
570 if (menu_items[i].subitems)
572 widget = ui_build_menu(menu, XmMENU_PULLDOWN,
573 menu_items[i].num_columns,
576 (MenuItem *)menu_items[i].subitems);
578 XtVaSetValues(widget, XmNuserData, (XtArgVal)menu_items[i].user_data, NULL);
582 widget = XtVaCreateManagedWidget(menu_items[i].name,
583 *menu_items[i].wclass,
585 XmNuserData, (XtArgVal)menu_items[i].user_data,
588 if (menu_items[i].label != NULL)
590 xmlabel = XmStringCreateLocalized(menu_items[i].label);
591 XtVaSetValues(widget, XmNlabelString, xmlabel, NULL);
592 XmStringFree(xmlabel);
595 /* If label is glyph type, then change type and call
596 * routine to set glyph.
598 if (menu_items[i].label_type == AB_LABEL_GLYPH)
600 XtVaSetValues(widget, XmNlabelType, XmPIXMAP, NULL);
601 dtb_set_label_from_bitmap_data(widget,
602 menu_items[i].pixwidth,
603 menu_items[i].pixheight,
609 if (menu_items[i].active == FALSE)
610 XtSetSensitive(widget, FALSE);
611 else if (menu_items[i].callback != NULL)
612 XtAddCallback(widget, XmNactivateCallback,
613 menu_items[i].callback,
614 menu_items[i].client_data);
617 if (menu_type == XmMENU_POPUP)
624 ui_populate_pulldown_menu(
641 XtSetArg(args[n], XmNpacking, XmPACK_COLUMN); n++;
642 XtSetArg(args[n], XmNnumColumns, num_columns); n++;
644 XtSetValues(menu, args, n);
647 for (i = 0; menu_items[i].label != NULL; i++)
649 if (menu_items[i].subitems)
651 widget = ui_build_menu(menu, XmMENU_PULLDOWN,
652 menu_items[i].num_columns,
655 (MenuItem *)menu_items[i].subitems);
657 XtVaSetValues(widget, XmNuserData, (XtArgVal)menu_items[i].user_data, NULL);
661 widget = XtVaCreateManagedWidget(menu_items[i].name,
662 *menu_items[i].wclass,
664 XmNuserData, (XtArgVal)menu_items[i].user_data,
667 if (menu_items[i].label != NULL)
669 xmlabel = XmStringCreateLocalized(menu_items[i].label);
670 XtVaSetValues(widget, XmNlabelString, xmlabel, NULL);
671 XmStringFree(xmlabel);
674 /* If label is glyph type, then change type and call
675 * routine to set glyph.
677 if (menu_items[i].label_type == AB_LABEL_GLYPH)
679 XtVaSetValues(widget, XmNlabelType, XmPIXMAP, NULL);
680 dtb_set_label_from_bitmap_data(widget,
681 menu_items[i].pixwidth,
682 menu_items[i].pixheight,
688 if (menu_items[i].active == FALSE)
689 XtSetSensitive(widget, FALSE);
690 else if (menu_items[i].callback != NULL)
691 XtAddCallback(widget, XmNactivateCallback,
692 menu_items[i].callback,
693 menu_items[i].client_data);
702 unsigned short width,
703 unsigned short height,
711 Dimension spacing = 0;
712 Dimension text_spacing = 0;
713 Dimension hsb_height = 0;
714 Dimension vsb_width = 0;
715 Dimension margin_w = 0;
716 Dimension margin_h = 0;
717 Dimension p_margin_w = 0;
718 Dimension p_margin_h = 0;
721 unsigned long charwidth;
722 unsigned long lineheight;
723 Dimension pane_width, pane_height;
725 if (XtIsSubclass(text, dtTermWidgetClass))
727 XmNmarginWidth, &margin_w,
728 XmNmarginHeight,&margin_h,
729 DtNuserFont, &fontlist,
733 XmNmarginWidth, &margin_w,
734 XmNmarginHeight,&margin_h,
735 XmNfontList, &fontlist,
736 XmNlistSpacing, &text_spacing,
739 parent = XtParent(text);
741 if (XtIsSubclass(parent, xmScrolledWindowWidgetClass))
743 XtVaGetValues(parent,
744 XmNhorizontalScrollBar, &hsb,
745 XmNverticalScrollBar, &vsb,
746 XmNspacing, &spacing,
750 XmNheight, &hsb_height,
754 XmNwidth, &vsb_width,
757 else if (XtIsSubclass(parent, xmRowColumnWidgetClass))
758 XtVaGetValues(parent,
759 XmNmarginWidth, &p_margin_w,
760 XmNmarginHeight, &p_margin_h,
763 font = objxm_fontlist_to_font(fontlist);
765 if ((!XGetFontProperty(font, XA_QUAD_WIDTH, &charwidth)) || charwidth == 0) {
766 if (font->per_char && font->min_char_or_byte2 <= '0' &&
767 font->max_char_or_byte2 >= '0')
768 charwidth = font->per_char['0' - font->min_char_or_byte2].width;
770 charwidth = font->max_bounds.width;
772 lineheight = font->max_bounds.ascent + font->max_bounds.descent +
775 /* Calculate new pane size */
776 pane_width = width - (vsb_width + spacing) - (2*p_margin_w);
777 pane_height = height - (hsb_height + spacing) - (2*p_margin_h);
779 *row_ptr = (int)((pane_height - (2*margin_h))/lineheight);
780 *col_ptr = (int)((pane_width - (2*margin_w))/charwidth);
782 /* For some reason, above calculations result in rows being 1 too
783 * large for a scrolled list widget; put in workaround until
784 * error in calculations is found...
787 REMIND: versions of Motif beyond August 10 don't need this
788 if (XtIsSubclass(text, xmListWidgetClass) && *row_ptr > 1)
800 static Cursor busy_cursor = NULL;
801 static Display *dpy = NULL;
803 if (on) /* Turn ON busy cursor */
805 dpy = XtDisplay(AB_toplevel);
807 if (busy_cursor == NULL)
808 busy_cursor = XCreateFontCursor(dpy, XC_watch);
810 XDefineCursor(dpy, window, busy_cursor);
812 else if (dpy != NULL) /* Turn OFF busy cursor */
814 XUndefineCursor(dpy, window);
823 * Initialize object pixmaps
836 unsigned int w, h, d, bw;
838 static int init = False;
839 extern Widget AB_toplevel;
842 * Return immediately if this function was called once before
847 dpy = XtDisplay(AB_toplevel);
850 * Loop thru object_pixmaps array uintil until last entry.
851 * The last entry should have type == AB_TYPE_UNKNOWN
853 for (i=0; (object_pixmaps[i].type != AB_TYPE_UNKNOWN); ++i)
858 status = dtb_cvt_image_file_to_pixmap(AB_toplevel,
859 object_pixmaps[i].filename, &tmp);
864 * Get width/height of pixmap
866 if (XGetGeometry(dpy, tmp, &root, &x, &y, &w, &h, &bw, &d))
868 object_pixmaps[i].pixmap = tmp;
869 object_pixmaps[i].width = w;
870 object_pixmaps[i].height = h;
873 fprintf(stderr, "XGetGeometry: returned error\n");
878 * Create default pixmap
880 status = dtb_cvt_image_file_to_pixmap(AB_toplevel,
881 "DtABdfl", &default_pixmap);
886 * Get default pixmap width/height
888 if (XGetGeometry(dpy, default_pixmap,
889 &root, &x, &y, &w, &h, &bw, &d))
891 default_pixmap_width = w;
892 default_pixmap_height = h;
895 fprintf(stderr, "XGetGeometry: returned error\n");
907 * based on an object's type and subtype, return a pixmap, and
908 * it's width/height. This pixmap typically can be used to represent
909 * the object in viewers/browsers.
915 Pixmap *pixmap, /* RETURN */
916 unsigned int *width, /* RETURN */
917 unsigned int *height /* RETURN */
926 if (!obj || !pixmap || !width || !height)
935 * Get object type/subtype
937 type = obj_get_type(obj);
938 subtype = obj_get_subtype(obj);
941 * Special case for scale/gauge
942 * The subtype field is not used. Instead it's read-only
943 * state is used to determine if it is a scale/gauge.
945 if (type == AB_TYPE_SCALE)
947 if (obj_get_read_only(obj) == False)
948 subtype = AB_SCALE_SCALE;
950 subtype = AB_SCALE_GAUGE;
954 * Search for object type/subtype match
956 for (i=0; (object_pixmaps[i].type != AB_TYPE_UNKNOWN); ++i)
958 if ((type == object_pixmaps[i].type) &&
959 (subtype == object_pixmaps[i].subtype))
961 *pixmap = object_pixmaps[i].pixmap;
962 *width = object_pixmaps[i].width;
963 *height = object_pixmaps[i].height;
973 * If no match, return the default pixmap
977 *pixmap = default_pixmap;
978 *width = default_pixmap_width;
979 *height = default_pixmap_height;
984 ui_add_window_close_callback(
986 XtCallbackProc delete_callback,
987 XtPointer client_data,
988 unsigned char delete_response
991 Atom WM_DELETE_WINDOW;
993 WM_DELETE_WINDOW = XmInternAtom(XtDisplay(shell), "WM_DELETE_WINDOW", False);
995 XtVaSetValues(shell, XmNdeleteResponse, delete_response, NULL);
996 XmAddWMProtocolCallback(shell, WM_DELETE_WINDOW, delete_callback, client_data);
1001 ui_remove_window_close_callback(
1003 XtCallbackProc delete_callback,
1004 XtPointer client_data
1007 Atom WM_DELETE_WINDOW;
1009 WM_DELETE_WINDOW = XmInternAtom(XtDisplay(shell),"WM_DELETE_WINDOW",False);
1010 XmRemoveWMProtocolCallback(shell,WM_DELETE_WINDOW,
1011 delete_callback, client_data);
1015 ui_add_window_iconify_handler(
1017 XtEventHandler iconify_proc,
1018 XtPointer client_data
1021 XtAddEventHandler(shell, StructureNotifyMask, False, iconify_proc,
1022 (XtPointer)client_data);
1026 ui_remove_window_iconify_handler(
1028 XtEventHandler iconify_proc,
1029 XtPointer client_data
1032 XtRemoveEventHandler(shell, StructureNotifyMask, False, iconify_proc,
1033 (XtPointer)client_data);
1037 ui_refresh_widget_tree(
1041 WidgetList children;
1042 int num_children = 0;
1045 if (widget == NULL || !XtIsWidget(widget) || !XtIsRealized(widget))
1048 if (XtIsSubclass(widget, compositeWidgetClass))
1050 XtVaGetValues(widget,
1051 XmNnumChildren, &num_children,
1052 XmNchildren, &children,
1055 /* Use recursion to traverse all the way to leaf nodes...*/
1056 for (i=0; i < num_children; i++)
1057 ui_refresh_widget_tree(children[i]);
1059 XClearArea(XtDisplay(widget), XtWindow(widget), 0, 0, 0, 0, TRUE);
1064 event_is_expose(XEvent *event)
1066 Bool is_expose = FALSE;
1068 switch (event->type)
1073 case GraphicsExpose:
1078 case VisibilityNotify:
1089 XtPointer clientData,
1090 XtIntervalId *intervalIdPtr
1093 SyncData syncData = (SyncData)clientData;
1094 time_t cur_time = time(NULL);
1097 if (syncData->synced)
1103 ((syncData->timeout_ticks - syncData->last_expose_ticks) >= 5);
1108 Display *display = syncData->display;
1109 Window window = syncData->window;
1112 long event_mask = 0;
1114 syncData->synced = TRUE;
1119 event.type = ClientMessage;
1120 event.xclient.display = display;
1121 event.xclient.window = window;
1122 event.xclient.message_type = 0;
1123 event.xclient.format = 32;
1124 for (i = 0; i < 8; ++i)
1126 event.xclient.data.l[i] = sync_notify_value;
1128 rc = XSendEvent(display, window, True, event_mask, &event);
1131 util_dprintf(0, "BIG TIME ERROR: send event failed\n");
1135 if (!(syncData->synced))
1137 syncData->timerId = XtAppAddTimeOut(
1138 XtWidgetToApplicationContext(AB_toplevel), 100,
1139 sync_timeout_proc, (XtPointer)clientData);
1142 ++(syncData->timeout_ticks);
1147 ui_sync_display_of_widget(Widget widget)
1149 int return_value = 0;
1150 XtAppContext appContext =
1151 XtWidgetToApplicationContext(widget);
1152 XEvent eventRec, *event = &eventRec;
1153 SyncDataRec syncData;
1154 Bool ignore_event = FALSE;
1155 Widget ancestor = widget;
1156 Widget last_ancestor = ancestor;
1157 Widget sync_widget = NULL;
1158 Screen *screen = NULL;
1160 syncData.timerId = 0;
1161 syncData.synced = FALSE;
1162 syncData.start_time = time(NULL);
1163 syncData.last_expose_ticks = 0;
1164 syncData.timeout_ticks = 0;
1165 syncData.display = NULL;
1166 syncData.window = NULL;
1167 #define last_expose_ticks (syncData.last_expose_ticks)
1168 #define synced (syncData.synced)
1169 #define timeout_ticks (syncData.timeout_ticks)
1171 syncData.display = XtDisplay(widget);
1172 screen = XtScreen(widget);
1173 syncData.window = RootWindowOfScreen(screen);
1176 * Find topmost parent of this widget that belongs to application.
1177 * This is in case this widget is destroyed (common for popups)
1179 last_ancestor = ancestor = widget;
1180 while ((ancestor != NULL) &&
1181 (XtWidgetToApplicationContext(ancestor) == appContext))
1183 last_ancestor = ancestor;
1184 ancestor = XtParent(ancestor);
1186 sync_widget = last_ancestor;
1187 syncData.window = XtWindow(sync_widget);
1189 syncData.timerId = XtAppAddTimeOut(appContext, 100,
1190 sync_timeout_proc, (XtPointer)&syncData);
1194 XtAppNextEvent(appContext, event);
1195 ignore_event = ( (event->type == ClientMessage)
1196 && (event->xclient.data.l[0] == sync_notify_value));
1199 XtDispatchEvent(event);
1202 if (event_is_expose(event))
1204 last_expose_ticks = timeout_ticks;
1206 if (difftime(time(NULL), syncData.start_time) >= 5)
1208 /* we've done this long enough - give up */
1211 } /* while !synced */
1213 XtRemoveTimeOut(syncData.timerId); syncData.timerId = 0;
1214 return return_value;
1215 #undef last_expose_ticks
1217 #undef timeout_ticks
1221 * Rubber banding convenience routines
1225 * Rubberbanding has just finished.
1226 * Finish up rubber banding:
1227 * - erase last box drawn
1228 * - call rubber band func
1229 * - reset some state variables
1235 XtPointer client_data
1240 /* erase last box */
1241 x_box_r(rb_widget, &rb_rect);
1244 * If a rubber band func was supplied, call it
1246 if (rubberband_func)
1247 rubberband_func(widget, event, &rb_rect, client_data);
1249 rubberband_func = NULL;
1250 rb_first_time = TRUE;
1255 * EventHandler: rubberband action is completed...
1256 * Call rubberband_finish() which calls the rubber
1262 XtPointer client_data,
1264 Boolean *cont_dispatch
1267 if (event->type != ButtonRelease)
1270 if (rband_in_progress)
1272 XtUngrabPointer(widget, CurrentTime);
1273 XtRemoveEventHandler(widget, ButtonReleaseMask, False,
1274 rubberband_release, client_data);
1275 rband_in_progress = False;
1279 rubberband_finish(widget, event, client_data);
1280 just_rbanded = False;
1281 *cont_dispatch = False;
1288 * Draws the rubber band box seen when the mouse is dragged
1294 XtPointer client_data
1299 if (event->type == ButtonPress)
1301 x = (short)((XButtonEvent*)event)->x;
1302 y = (short)((XButtonEvent*)event)->y;
1304 else if (event->type == MotionNotify)
1306 x = (short)((XMotionEvent*)event)->x;
1307 y = (short)((XMotionEvent*)event)->y;
1319 rb_first_time = FALSE;
1322 x_box_r(rb_widget, &rb_rect);
1324 rb_rect.width = x - rb_rect.x;
1325 rb_rect.height = y - rb_rect.y;
1327 x_box_r(rb_widget, &rb_rect);
1332 * Starts up the rubber band UI.
1333 * It grab the pointer and adds an event handler
1334 * which detects the ButtonRelease. It also sets the
1338 ui_initiate_rubberband(
1340 Boolean confine_to_window,
1341 UiRubberBandFunc rb_func,
1342 XtPointer client_data
1346 XtAddEventHandler(widget, ButtonReleaseMask, False,
1347 rubberband_release, client_data);
1349 if (XtGrabPointer(widget, False,
1350 ButtonReleaseMask | ButtonMotionMask | PointerMotionMask,
1351 GrabModeAsync, GrabModeAsync,
1352 confine_to_window ? XtWindow(widget) : None,
1353 NULL, CurrentTime) == GrabSuccess)
1355 rband_in_progress = True;
1356 rubberband_func = rb_func;
1360 rband_in_progress = False;
1361 rubberband_func = NULL;
1367 * ui_button_drag: drag action ...
1368 * Called by the drag button event handler for the widget
1369 * where rubber banding is desired.
1375 XtPointer client_data
1378 if (event->type == MotionNotify)
1380 if (rband_in_progress)
1382 rubberband_draw(widget, event, client_data);
1383 just_rbanded = True;
1390 ui_optionmenu_add_item(
1396 Widget cascade_btn = NULL;
1401 if ((cascade_btn = XmOptionButtonGadget(opmenu)) != NULL)
1403 XtVaGetValues(cascade_btn, XmNsubMenuId, &menu, NULL);
1406 xmitem = XmStringCreateLocalized(item_str);
1407 mpb = XtVaCreateManagedWidget(item_str,
1408 xmPushButtonWidgetClass,
1410 XmNlabelString, xmitem,
1412 XmStringFree(xmitem);
1420 ui_optionmenu_delete_item(
1428 item = ui_optionmenu_find_item(opmenu, item_str);
1431 XtDestroyWidget(item);
1442 ui_optionmenu_replace_item(
1444 STRING old_item_str,
1449 Widget opmenu_label = NULL;
1450 XmString xmstr = NULL;
1451 XmString new_item_xmstr = NULL;
1452 XmString old_item_xmstr = NULL;
1454 item = ui_optionmenu_find_item(opmenu, old_item_str);
1457 new_item_xmstr = XmStringCreateLocalized(new_item_str);
1459 /* Check if the item we're replacing is the one
1460 * which is currently showing in the optionmenu.
1461 * If so, change the string.
1463 old_item_xmstr = XmStringCreateLocalized(old_item_str);
1464 opmenu_label = XmOptionButtonGadget(opmenu);
1465 XtVaGetValues(opmenu_label, XmNlabelString, &xmstr, NULL);
1466 if (XmStringCompare(xmstr, old_item_xmstr))
1468 XtVaSetValues(opmenu_label,
1469 XmNlabelString, new_item_xmstr,
1473 /* Change the button label to the new string */
1474 XtVaSetValues(item, XmNlabelString, new_item_xmstr, NULL);
1476 XmStringFree(xmstr);
1477 XmStringFree(old_item_xmstr);
1478 XmStringFree(new_item_xmstr);
1484 ui_optionmenu_find_item(
1489 Widget cascade_btn = NULL;
1491 Widget found_item = NULL;
1492 WidgetList children = NULL;
1493 XmString search_item, child = NULL;
1494 int i, numChildren = 0;
1497 if ((cascade_btn = XmOptionButtonGadget(opmenu)) != NULL)
1499 XtVaGetValues(cascade_btn, XmNsubMenuId, &menu, NULL);
1502 search_item = XmStringCreateLocalized(item_str);
1504 XmNnumChildren, &numChildren,
1505 XmNchildren, &children,
1507 for (i=0; i < numChildren && !Found; i++)
1509 XtVaGetValues(children[i], XmNlabelString, &child, NULL);
1510 if (XmStringCompare(search_item, child))
1513 found_item = children[i];
1516 XmStringFree(search_item);
1517 XmStringFree(child);
1520 return (found_item);
1524 ui_optionmenu_num_items(
1528 Widget cascade_btn = NULL;
1530 int numChildren = 0;
1532 if ( (opmenu != NULL) &&
1533 ((cascade_btn = XmOptionButtonGadget(opmenu)) != NULL)
1536 XtVaGetValues(cascade_btn, XmNsubMenuId, &menu, NULL);
1540 XmNnumChildren, &numChildren,
1544 return (numChildren);
1549 ui_optionmenu_change_label(
1554 Widget opmenu_label = NULL;
1556 XmString old_xmstr = NULL;
1558 opmenu_label = XmOptionButtonGadget(opmenu);
1559 if ((opmenu_label != NULL) && (new_str != NULL))
1561 new_xmstr = XmStringCreateLocalized(new_str);
1562 XtVaGetValues(opmenu_label, XmNlabelString, &old_xmstr, NULL);
1564 /* If the two labels are different, then change
1565 * the optionmenu label.
1567 if (!XmStringCompare(old_xmstr, new_xmstr))
1569 XtVaSetValues(opmenu_label,
1570 XmNlabelString, new_xmstr,
1573 XmStringFree(new_xmstr);
1578 ui_optionmenu_change_label_pixmap(
1583 Widget opmenu_label;
1585 opmenu_label = XmOptionButtonGadget(opmenu);
1587 if (opmenu_label != NULL)
1589 XtVaSetValues(opmenu_label,
1590 XmNlabelPixmap, pixmap,
1591 XmNlabelType, XmPIXMAP,
1597 ** Set the label string on an object
1598 ** (converts it to XmString internally, if needed)
1601 ui_obj_set_label_string(
1606 ABObj labelObj = NULL;
1611 switch (obj_get_type(obj))
1613 case AB_TYPE_BUTTON:
1614 case AB_TYPE_CHOICE:
1615 case AB_TYPE_COMBO_BOX:
1618 case AB_TYPE_SPIN_BOX:
1620 case AB_TYPE_TEXT_FIELD:
1621 labelObj = objxm_comp_get_subobj(obj, AB_CFG_LABEL_OBJ);
1622 if (labelObj == NULL || objxm_get_widget(labelObj) == NULL)
1625 ui_set_label_string(objxm_get_widget(labelObj), label);
1629 switch(obj_get_item_type(obj))
1631 case AB_ITEM_FOR_MENU:
1632 case AB_ITEM_FOR_MENUBAR:
1633 case AB_ITEM_FOR_CHOICE:
1634 labelObj = objxm_comp_get_subobj(obj, AB_CFG_LABEL_OBJ);
1635 if (labelObj == NULL || objxm_get_widget(labelObj) == NULL)
1638 ui_set_label_string(objxm_get_widget(labelObj), label);
1641 case AB_ITEM_FOR_COMBO_BOX:
1642 case AB_ITEM_FOR_LIST:
1643 case AB_ITEM_FOR_SPIN_BOX:
1645 ABObj p_obj = obj_get_parent(obj);
1646 Widget parent = objxm_get_widget(p_obj);
1647 AB_ITEM_TYPE itype = (AB_ITEM_TYPE)obj_get_subtype(obj);
1654 xmitem = XmStringCreateLocalized(label);
1655 pos = obj_get_child_num(obj);
1656 pos++; /* XmList starts at 1 */
1658 if (obj_is_combo_box_item(obj))
1659 parent = ui_combobox_get_list_widget(parent);
1661 if (obj_is_list_item(obj) ||
1662 obj_is_combo_box_item(obj))
1663 XtVaGetValues(parent,
1664 XmNitemCount, &num_items,
1666 else if (obj_is_spin_box_item(obj))
1667 XtVaGetValues(parent,
1668 DtNnumValues, &num_items,
1671 if (pos <= num_items)
1673 if (obj_is_list_item(obj) ||
1674 obj_is_combo_box_item(obj))
1676 XmListReplacePositions(parent, &pos,
1681 DtSpinBoxDeletePos(parent, pos);
1682 DtSpinBoxAddItem(parent, xmitem, pos);
1685 XmStringFree(xmitem);
1695 case AB_TYPE_BASE_WINDOW:
1696 case AB_TYPE_DIALOG:
1697 case AB_TYPE_FILE_CHOOSER:
1698 labelObj = objxm_comp_get_subobj(obj, AB_CFG_LABEL_OBJ);
1699 if (labelObj == NULL || objxm_get_widget(labelObj) == NULL)
1702 XtVaSetValues(objxm_get_widget(labelObj), XmNtitle, label, NULL);
1711 ** Set the label glyph (ie graphic) on an object
1714 ui_obj_set_label_glyph(
1719 ABObj labelObj = NULL;
1724 if (util_strempty(fileName))
1727 labelObj = objxm_comp_get_subobj(obj, AB_CFG_LABEL_OBJ);
1728 if (labelObj == NULL || objxm_get_widget(labelObj) == NULL)
1731 switch (obj_get_type(obj))
1733 case AB_TYPE_BUTTON:
1734 case AB_TYPE_CHOICE:
1735 case AB_TYPE_COMBO_BOX:
1738 case AB_TYPE_SPIN_BOX:
1740 case AB_TYPE_TEXT_FIELD:
1741 ui_set_label_glyph(objxm_get_widget(labelObj), fileName);
1745 switch(obj_get_item_type(obj))
1747 case AB_ITEM_FOR_MENU:
1748 case AB_ITEM_FOR_MENUBAR:
1749 case AB_ITEM_FOR_CHOICE:
1750 ui_set_label_glyph(objxm_get_widget(labelObj), fileName);
1764 ** Set the label on an object
1765 ** string and glyphs are supported
1776 switch (obj_get_label_type(obj))
1778 case AB_LABEL_STRING:
1779 ui_obj_set_label_string(obj, label);
1782 case AB_LABEL_GLYPH:
1783 ui_obj_set_label_glyph(obj, label);