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
24 * $XConsortium: abobj_events.c /main/3 1995/11/06 17:15:49 rswiston $
26 * @(#)abobj_events.c 1.50 15 Feb 1994 cde_app_builder/src/ab
28 * RESTRICTED CONFIDENTIAL INFORMATION:
30 * The information in this document is subject to special
31 * restrictions in a confidential disclosure agreement between
32 * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
33 * document outside HP, IBM, Sun, USL, SCO, or Univel without
34 * Sun's specific written approval. This document and all copies
35 * and derivative works thereof must be returned or destroyed at
38 * Copyright 1993 Sun Microsystems, Inc. All rights reserved.
44 ***********************************************************************
45 * abobj_events.c - implements UI object 'behavior' for created
49 ***********************************************************************
52 #include <X11/keysym.h>
54 #include <Xm/XmStrDefs.h>
55 #include <Xm/DrawingA.h>
57 #include <Xm/ScrolledW.h>
60 #include <Xm/FileSB.h>
61 #include <Dt/ComboBox.h>
62 #include <Dt/MenuButton.h>
63 #include <Dt/SpinBox.h>
64 #include <ab_private/trav.h>
65 #include <ab_private/objxm.h>
66 #include <ab_private/ab.h>
67 #include <ab_private/pal.h>
69 #include <ab_private/x_util.h>
70 #include <ab_private/ui_util.h>
71 #include <ab_private/conn.h>
72 #include <ab_private/brws.h>
73 #include <ab_private/prop.h>
74 #include "palette_ui.h"
77 #define AB_MAX_TRANSTBLS 70
80 * Structure to store info related to implementing programmatic
81 * double-click on widgets where the translation does not work
84 typedef struct DOUBLE_CLICK_INFO {
87 unsigned int interval;
93 /*************************************************************************
95 ** Private Function Declarations **
97 **************************************************************************/
101 static void object_button_press(
107 static void object_mouse_enter(
113 static void object_mouse_leave(
119 static void object_mouse_motion(
125 static void object_select(
131 static void object_toggle_select(
137 static void object_invoke_props(
143 static void object_popup_menu(
149 static void objects_pixel_move(
157 * Widget Event Handlers
159 static void interpose_button_event(
165 static void object_button_drag(
171 static void object_move_release(
177 static void object_resize_release(
183 static void object_mselect(
187 XtPointer client_data
189 static void object_track_move(
195 static void object_track_iconify(
201 static void prevent_closeCB(
203 XtPointer client_data,
206 static void wait_for_double(
207 XtPointer client_data,
208 XtIntervalId timer_id
212 * Private Internal Procs
214 static int initiate_move(
219 static int initiate_resize(
225 static int initiate_mselect(
230 /*************************************************************************
234 **************************************************************************/
239 XtActionsRec build_actions[] = {
240 {"ObjectMouseEnter", (XtActionProc)object_mouse_enter },
241 {"ObjectMouseLeave", (XtActionProc)object_mouse_leave },
242 {"ObjectMouseMotion", (XtActionProc)object_mouse_motion },
243 {"ObjectSelect", (XtActionProc)object_select },
244 {"ObjectButtonPress", (XtActionProc)object_button_press },
245 {"ObjectToggleSelect", (XtActionProc)object_toggle_select },
246 {"ObjectInvokeProps", (XtActionProc)object_invoke_props },
247 {"ObjectPopupMenu", (XtActionProc)object_popup_menu },
248 {"ObjectDragChord", (XtActionProc)conn_drag_chord },
249 {"ObjectsPixelMove", (XtActionProc)objects_pixel_move }
253 * Build-Mode Translations
255 String base_translations =
256 "<Enter>: ObjectMouseEnter() \n\
257 <Leave>: ObjectMouseLeave() \n\
258 <Motion>: ObjectMouseMotion() \n\
259 Ctrl <Btn1Down>: ObjectDragChord() \n\
260 Shift <Btn1Down>: ObjectButtonPress() \n\
261 Shift <Btn1Down>,<Btn1Up>:ObjectToggleSelect() \n\
262 <Btn1Down>: ObjectButtonPress() \n\
263 <Btn1Down>,<Btn1Up>: ObjectSelect() \n\
264 <Btn1Up>(2): ObjectInvokeProps() \n\
265 <Key>Left: ObjectsPixelMove() \n\
266 <Key>Right: ObjectsPixelMove() \n\
267 <Key>Down: ObjectsPixelMove() \n\
268 <Key>Up: ObjectsPixelMove() \n"; /* will be appended-to */
270 String btn2_adjust_translations =
271 "<Btn2Down>: ObjectButtonPress() \n\
272 <Btn2Down>,<Btn2Up>: ObjectToggleSelect() \n"; /* will be appended-to */
274 String btn3_menu_translations =
275 "<Btn3Down>: ObjectPopupMenu()";
277 String btn2_menu_translations =
278 "<Btn2Down>: ObjectPopupMenu()";
280 static XtTranslations build_transtbl = NULL;
284 extern const int AB_drag_threshold;
286 static RESIZE_DIR resize_dir = NONE;
287 static Boolean just_moved = False;
288 static Boolean just_mselected = False;
289 static Boolean potential_move = False;
290 static Boolean move_in_progress = False;
291 static Boolean resize_in_progress = False;
292 static Boolean mselect_in_progress= False;
293 static Boolean mselect_adjust = False;
294 static Boolean actions_init = False;
296 /*************************************************************************
298 ** Function Definitions **
300 **************************************************************************/
303 * Traverse tree and set the mode of behavior ("build" or "test")
304 * for each object with a valid ui_handle (instantiated widget ID)
307 abobj_tree_set_build_actions(
317 /* set the appropriate build actions */
318 for (trav_open(&trav, root, AB_TRAV_UI);
319 (obj = trav_next(&trav)) != NULL; )
321 if (objxm_get_widget(obj) != NULL)
323 if (AB_builder_mode == MODE_BUILD)
324 abobjP_enable_build_actions(obj, objxm_get_widget(obj));
326 abobjP_disable_build_actions(obj, objxm_get_widget(obj));
335 * Register build actions with Xt
338 abobj_register_build_actions(
343 /* Register Build Actions */
344 XtAppAddActions(app, build_actions, XtNumber(build_actions));
350 enable_on_internal_widgets(
357 int num_children = 0;
360 XtVaGetValues(widget,
361 XtNnumChildren, &num_children,
362 XtNchildren, &children,
365 for (i = 0; i < num_children; ++i)
367 if (!XtIsWidget(children[i]) ||
368 XtIsSubclass(children[i], shellWidgetClass) ||
369 XtIsSubclass(children[i], xmTextWidgetClass) ||
370 XtIsSubclass(children[i], xmDrawingAreaWidgetClass))
373 objxm_store_obj_and_actions(children[i], obj);
375 XtVaSetValues(children[i],
376 XtNtranslations, build_transtbl,
379 XtAddEventHandler(children[i], Button1MotionMask | Button2MotionMask,
380 False, object_button_drag, (XtPointer)root);
383 if (XtIsSubclass(children[i], compositeWidgetClass))
384 enable_on_internal_widgets(children[i], obj, root);
389 disable_on_internal_widgets(
396 int num_children = 0;
397 XtTranslations orig_trans;
400 XtVaGetValues(widget,
401 XtNnumChildren, &num_children,
402 XtNchildren, &children,
405 for (i = 0; i < num_children; ++i)
407 if (!XtIsWidget(children[i]) ||
408 XtIsSubclass(children[i], shellWidgetClass) ||
409 XtIsSubclass(children[i], xmTextWidgetClass) ||
410 XtIsSubclass(children[i], xmDrawingAreaWidgetClass))
413 XtRemoveEventHandler(children[i],
414 Button1MotionMask | Button2MotionMask,
416 object_button_drag, (XtPointer)root);
418 orig_trans = objxm_get_actions_from_widget(children[i]);
421 XtVaSetValues(children[i],
422 XtNtranslations, orig_trans,
425 XtUninstallTranslations(children[i]);
428 if (XtIsSubclass(children[i], compositeWidgetClass))
429 disable_on_internal_widgets(children[i], obj, root);
435 * Enable build-mode behavior for the widget
438 abobjP_enable_build_actions(
444 ABObj rootObj = obj_get_root(obj);
446 if (obj_has_flag(obj, BuildActionsFlag))
447 return; /* Already has actions */
449 if (objxm_is_menu_widget(widget) || obj_is_menu_item(obj))
452 /* Window objects require specialized event tracking */
453 if (obj_is_window(obj) && XtIsSubclass(widget, shellWidgetClass))
455 /* Prevent the user from "Quitting" a window in build-mode*/
456 ui_add_window_close_callback(widget, prevent_closeCB, NULL, XmDO_NOTHING);
458 /* Track when a window is iconified */
459 if (obj_is_base_win(obj))
460 ui_add_window_iconify_handler(widget, object_track_iconify, (XtPointer)obj);
462 /* Track when the user moves the window so that if it is re-instantiated,
463 * it will appear in the position the user placed it in.
464 * NOTE: this does not set a permanent position attribute for a window!
466 XtAddEventHandler(widget, StructureNotifyMask, False,
467 (XtEventHandler)object_track_move, (XtPointer)rootObj);
471 if (build_transtbl == NULL)
474 String build_translations, menu_translations;
477 * Build up translation table based on the number of mouse buttons
478 * and the value of the display resource, "enableBtn1Transfer".
480 menu_translations = (AB_BMenu == Button3? btn3_menu_translations : btn2_menu_translations);
482 len = strlen(base_translations) + strlen(menu_translations) + 1;
484 if (AB_BMenu == Button3 && AB_btn1_transfer == True)
485 /* Button2 can be used for ADJUST */
486 len += strlen(btn2_adjust_translations);
488 build_translations = (String)util_malloc(len*sizeof(char));
489 if (build_translations == NULL)
492 /* Build Translation table */
493 strcpy(build_translations, base_translations);
494 if (AB_BMenu == Button3 && AB_btn1_transfer == True)
495 strcat(build_translations, btn2_adjust_translations);
496 strcat(build_translations, menu_translations);
498 build_transtbl = XtParseTranslationTable(build_translations);
500 util_free(build_translations);
503 /* Enable build mode behavior */
504 XtVaSetValues(widget,
505 XtNtranslations, build_transtbl,
508 if (obj_is_item(obj))
509 evObj = obj_get_parent(obj);
513 /* The DtMenuButton widget uses an internal event-handler to post its menu,
514 * so our standard translations will not get called. Therefore, we use
515 * an event-handler to get these buttons events before the widget does.
517 if (XtIsSubclass(widget, dtMenuButtonWidgetClass))
518 XtInsertEventHandler(widget,
519 ButtonMotionMask | ButtonPressMask | ButtonReleaseMask,
520 False, interpose_button_event, (XtPointer)rootObj, XtListHead);
522 /* Track drag events on all other widgets */
523 else if (!(obj_is_sub(obj) && obj_is_window(rootObj)) &&
524 !obj_is_menubar(rootObj))
525 XtAddEventHandler(widget, Button1MotionMask | Button2MotionMask, False,
526 object_button_drag, (XtPointer)rootObj);
528 /* Track size changes caused internally & externally */
529 if (objxm_comp_get_subobj(rootObj, AB_CFG_SIZE_OBJ) == obj)
530 XtAddEventHandler(widget, StructureNotifyMask, False,
531 (XtEventHandler)abobjP_track_external_resizes, (XtPointer)rootObj);
533 /* Ensure all this stuff gets registered on *internal* widgets as well */
534 if ((XtIsSubclass(widget, xmScrolledWindowWidgetClass) &&
535 !XtIsSubclass(widget, xmMainWindowWidgetClass)) ||
536 XtIsSubclass(widget, dtComboBoxWidgetClass) ||
537 XtIsSubclass(widget, xmScaleWidgetClass) ||
538 XtIsSubclass(widget, xmFileSelectionBoxWidgetClass) ||
539 XtIsSubclass(widget, dtSpinBoxWidgetClass))
540 enable_on_internal_widgets(widget, obj, rootObj);
542 obj_set_flag(obj, BuildActionsFlag);
547 * Disable build-mode behavior for the widget
550 abobjP_disable_build_actions(
556 ABObj rootObj = obj_get_root(obj);
557 XtTranslations orig_trans;
559 if (obj_is_window(obj) && XtIsSubclass(widget, shellWidgetClass))
561 ui_remove_window_close_callback(widget, prevent_closeCB, NULL);
563 if (obj_is_base_win(obj))
564 ui_remove_window_iconify_handler(widget, object_track_iconify, (XtPointer)obj);
566 XtRemoveEventHandler(widget, StructureNotifyMask, False,
567 (XtEventHandler)object_track_move, (XtPointer)rootObj);
570 /* Don't bother for Shells or menu-related widgets */
571 if (XtIsSubclass(widget, shellWidgetClass) ||
572 objxm_is_menu_widget(widget) || obj_is_menu_item(obj))
575 if (!obj_has_flag(obj, BuildActionsFlag))
576 return; /* No actions to disable */
578 if (obj_is_item(obj))
579 evObj = obj_get_parent(obj);
585 if (XtIsSubclass(widget, dtMenuButtonWidgetClass))
586 XtRemoveEventHandler(widget,
587 ButtonMotionMask | ButtonPressMask | ButtonReleaseMask,
588 False, interpose_button_event, (XtPointer)rootObj);
590 else if (!(obj_is_sub(obj) && obj_is_window(rootObj)) &&
591 !(obj_is_menubar(rootObj)))
592 XtRemoveEventHandler(widget, Button1MotionMask | Button2MotionMask, False,
593 object_button_drag, (XtPointer)rootObj);
595 if (objxm_comp_get_subobj(rootObj, AB_CFG_SIZE_OBJ) == obj)
596 XtRemoveEventHandler(widget, StructureNotifyMask, False,
597 (XtEventHandler)abobjP_track_external_resizes, (XtPointer)rootObj);
599 orig_trans = objxm_get_actions_from_widget(widget);
602 * if no original translations, uninstall instead of setting
603 * XtNtranslations to NULL because this may not have any
607 XtVaSetValues(widget, XtNtranslations, orig_trans, NULL);
609 XtUninstallTranslations(widget);
611 if ((XtIsSubclass(widget, xmScrolledWindowWidgetClass) &&
612 !XtIsSubclass(widget, xmMainWindowWidgetClass)) ||
613 XtIsSubclass(widget, dtComboBoxWidgetClass) ||
614 XtIsSubclass(widget, xmScaleWidgetClass) ||
615 XtIsSubclass(widget, xmFileSelectionBoxWidgetClass) ||
616 XtIsSubclass(widget, dtSpinBoxWidgetClass))
617 disable_on_internal_widgets(widget, obj, rootObj);
619 obj_clear_flag(obj, BuildActionsFlag);
623 * Action: pointer has 'entered' widget
638 obj = objxm_get_obj_from_widget(widget);
642 rootObj = obj_is_item(obj)? obj_get_parent(obj) : obj;
644 rootObj = obj_get_root(rootObj);
646 sprintf(pos_str, "%3d,%3d", rootObj->x, rootObj->y);
647 sprintf(sz_str, "%3d X %3d",
648 abobj_get_actual_width(rootObj), abobj_get_actual_height(rootObj));
649 ab_update_stat_region(AB_STATUS_OBJ_TYPE, pal_get_item_subname(rootObj,obj_get_subtype(rootObj)));
650 ab_update_stat_region(AB_STATUS_OBJ_NAME, obj_get_name(rootObj));
651 ab_update_stat_region(AB_STATUS_OBJ_POS, pos_str);
652 ab_update_stat_region(AB_STATUS_OBJ_SIZE, sz_str);
657 * Action: pointer has 'left' widget
668 ab_update_stat_region(AB_STATUS_OBJ_TYPE, " ");
669 ab_update_stat_region(AB_STATUS_OBJ_NAME, " ");
670 ab_update_stat_region(AB_STATUS_CURS_POS, " ");
671 ab_update_stat_region(AB_STATUS_OBJ_POS, " ");
672 ab_update_stat_region(AB_STATUS_OBJ_SIZE, " ");
677 * Action: pointer has 'left' widget
687 ABObj obj = NULL, rootObj;
688 XMotionEvent *mevent = (XMotionEvent*)event;
692 obj = objxm_get_obj_from_widget(widget);
696 /* Make sure the x,y position is relative to the ROOT obj
697 * of a given obj or CompositeObj
699 rootObj = obj_is_item(obj)? obj_get_parent(obj) : obj;
700 rootObj = obj_get_root(rootObj);
702 x_widget_translate_xy(objxm_get_widget(obj), (XtPointer)objxm_get_widget(rootObj),
703 mevent->x, mevent->y, &rx, &ry);
710 sprintf(motionstr, "%3d,%3d", rx, ry);
711 ab_update_stat_region(AB_STATUS_CURS_POS, motionstr);
716 * Action: caused the object to become "selected"
728 obj = objxm_get_obj_from_widget(widget);
730 /* This action is called directly after a Move (on the Mouse
731 * button Release), therefore, IF a Move just occurred, DO NOT
732 * deselect all other selected objects...
735 abobj_deselect_all(obj_get_project(obj));
744 * Action: toggles the select-state of the object
747 object_toggle_select(
759 if (just_moved) /* BUTTON2 TRANSFER - don't toggle select! */
765 obj = objxm_get_obj_from_widget(widget);
766 rootObj = obj_get_root(obj);
767 if (obj_is_item(rootObj))
768 rootObj = obj_get_root(obj_get_parent(rootObj));
770 if (obj_is_selected(rootObj))
771 abobj_deselect(rootObj);
774 /* Only objects on the same level (siblings) may be
775 * selected at one time. If a non-sibling object is
776 * already selected, do not allow the new object to
779 abobj_get_selected(obj_get_window(rootObj), True, False, &sel);
781 for(i = 0; i < sel.count; i++)
783 if (!obj_is_sibling(rootObj, sel.list[i]))
787 abobj_select(rootObj);
795 * Action: invokes the property sheet for the object
807 obj = objxm_get_obj_from_widget(widget);
809 prop_load_obj(obj, AB_PROP_REVOLVING);
814 * Action: popup the build menu for the object
827 obj = objxm_get_obj_from_widget(widget);
829 abobj_get_selected(obj_get_window(obj), True, False, &sel);
831 if (event->type == ButtonPress)
832 abobj_popup_menu(WIN_EDIT_MENU, widget, &sel, (XButtonEvent *)event);
839 * Action: move selected objects by 1 pixel
855 if (event->type == KeyPress)
857 kevent = (XKeyEvent*)event;
859 obj = objxm_get_obj_from_widget(widget);
861 abobj_get_selected(obj_get_window(obj), False, False, &sel);
866 XtTranslateKeycode(kevent->display, kevent->keycode, kevent->state,
872 abobj_nudge_selected(sel.list, sel.count, 0, -1, True);
875 abobj_nudge_selected(sel.list, sel.count, 0, 1, True);
878 abobj_nudge_selected(sel.list, sel.count, 1, 0, True);
881 abobj_nudge_selected(sel.list, sel.count, -1, 0, True);
892 * grab the pointer to track the movement of the object
904 static Cursor move_cursor = NULL;
906 rootObj = obj_get_root(obj);
908 geomObj = objxm_comp_get_subobj(rootObj, AB_CFG_POSITION_OBJ);
909 geomWidget = objxm_get_widget(geomObj);
911 if (geomWidget == NULL)
913 util_dprintf(0,"initiate_move: no geometry widget\n");
916 parent = XtParent(geomWidget);
919 move_cursor = abobjP_get_resize_cursor(widget, MOVE);
921 XtAddEventHandler(widget, ButtonReleaseMask, False,
922 object_move_release, (XtPointer)rootObj);
924 if (XtGrabPointer(widget, False,
925 ButtonReleaseMask | ButtonMotionMask | PointerMotionMask,
926 GrabModeAsync, GrabModeAsync, XtWindow(parent),
927 move_cursor, CurrentTime) == GrabSuccess)
935 * Grab the pointer to interpret the resize action
947 Cursor resize_cursor;
949 rootObj = obj_get_root(obj);
950 geomObj = objxm_comp_get_subobj(rootObj, AB_CFG_SIZE_OBJ);
951 geomWidget = objxm_get_widget(geomObj);
953 if (geomWidget == NULL)
955 util_dprintf(0,"initiate_resize: no geometry widget\n");
959 resize_cursor = abobjP_get_resize_cursor(widget, dir);
961 XtAddEventHandler(widget, ButtonReleaseMask, False,
962 object_resize_release, (XtPointer)obj);
964 if (XtGrabPointer(widget, False,
965 ButtonReleaseMask | ButtonMotionMask | PointerMotionMask,
966 GrabModeAsync, GrabModeAsync, NULL,
967 resize_cursor, CurrentTime) == GrabSuccess)
976 * Action: mouse button down...
986 XButtonEvent *bevent;
990 potential_move = False;
993 obj = objxm_get_obj_from_widget(widget);
994 rootObj = obj_get_root(obj);
996 if (obj_is_window(rootObj))
999 if (event->type == ButtonPress)
1001 bevent = (XButtonEvent*)event;
1003 if (bevent->state == 0 &&
1004 (bevent->button == 1 ||
1005 (AB_btn1_transfer != True && bevent->button == 2)))
1006 /* MOVE, RESIZE or RUBBERBAND-SELECT */
1008 resize_dir = abobjP_find_resize_direction(obj, widget, event);
1010 if (resize_dir == MOVE) /* MOVE (pending subsequent drag event) */
1011 potential_move = True;
1013 else if (bevent->button == 1 && resize_dir == NONE && obj_is_pane(rootObj))
1015 if (obj_is_control_panel(rootObj))
1017 /* RUBBERBAND-SELECT */
1018 if (ui_initiate_rubberband(widget, False,
1019 object_mselect, (XtPointer)obj) == ERROR)
1021 mselect_in_progress = False;
1022 util_dprintf(0,"object_button_press: couldn't begin rubberband\n");
1026 mselect_in_progress = True;
1027 mselect_adjust = False;
1031 else if (bevent->button == 1) /* RESIZE */
1033 if (obj_is_selected(rootObj))
1035 if (initiate_resize(widget, obj, resize_dir) == ERROR)
1037 resize_in_progress = False;
1038 util_dprintf(0, "object_button_press: couldn't begin resize\n");
1041 resize_in_progress = True;
1045 else if (bevent->button == 2 ||
1046 (bevent->button == 1 && (bevent->state & ShiftMask))) /* RUBBERBAND-ADJUST */
1048 if (obj_is_control_panel(rootObj))
1050 if (ui_initiate_rubberband(widget, False,
1051 object_mselect, (XtPointer)obj) == ERROR)
1053 mselect_in_progress = False;
1054 util_dprintf(0,"object_button_press: couldn't begin rubberband\n");
1057 mselect_in_progress = mselect_adjust = True;
1064 * Xt Timer proc : used to detect a double-click event for widgets
1065 * where the translation doesn't work (DtMenuButton).
1069 XtPointer client_data,
1070 XtIntervalId timer_id
1073 DoubleClickInfo *d_click = (DoubleClickInfo*)client_data;
1075 /* Waiting interval for double-click expired.
1076 * Go ahead and process the single-click...
1078 d_click->waiting = False;
1079 object_button_press(d_click->widget, d_click->event, NULL, 0);
1084 * Event Handler: For widgets which use internal event-handlers for
1085 * button events, we must use an event-handler (instead
1086 * of translations) to grab these events. We simply
1087 * call the appropriate action procedure ourselves.
1090 interpose_button_event(
1092 XtPointer client_data,
1094 Boolean *cont_dispatch
1097 XButtonEvent *bevent;
1098 XMotionEvent *mevent;
1099 static XEvent event_cpy;
1100 static DoubleClickInfo *d_click = NULL;
1101 static XtIntervalId timer_id = NULL;
1102 ABObj obj = (ABObj)client_data;
1105 if (event->type == ButtonPress || event->type == ButtonRelease)
1107 bevent = (XButtonEvent*)event;
1109 /* absorb all button events */
1110 *cont_dispatch = False;
1112 switch(bevent->button)
1115 if (event->type == ButtonPress)
1117 if (bevent->state & ControlMask) /* Connections Accelerator */
1119 conn_drag_chord(widget, event, NULL, 0);
1123 if (d_click == NULL) /* Init DoubleClick structure */
1125 d_click = (DoubleClickInfo*)util_malloc(sizeof(DoubleClickInfo));
1126 if (d_click == NULL)
1127 return; /* yikes! */
1128 d_click->widget = NULL;
1129 d_click->event = NULL;
1130 d_click->interval = XtGetMultiClickTime(XtDisplay(widget));
1131 d_click->waiting = False;
1134 if (d_click->waiting) /* double-click occurred */
1136 XtRemoveTimeOut(timer_id);
1137 d_click->waiting = False;
1138 object_invoke_props(widget, event, NULL, 0);
1140 else if (bevent->state == 0) /* Start timing for double-click */
1143 d_click->waiting = True;
1144 d_click->widget = widget;
1145 d_click->event = &event_cpy;
1146 d_click->start_x = bevent->x;
1147 d_click->start_y = bevent->y;
1148 timer_id = XtAppAddTimeOut(
1149 XtWidgetToApplicationContext(widget),
1151 (XtTimerCallbackProc)wait_for_double,
1152 (XtPointer)d_click);
1158 else if (resize_in_progress)
1159 object_resize_release(widget, client_data, event, cont_dispatch);
1161 else if (move_in_progress) /* ButtonRelease */
1162 object_move_release(widget, client_data, event, cont_dispatch);
1164 else if (bevent->state & ShiftMask)
1165 object_toggle_select(widget, event, NULL, 0);
1168 object_select(widget, event, NULL, 0);
1172 if (event->type == ButtonPress && AB_btn1_transfer != True) /* BUTTON2 TRANSFER */
1173 object_button_press(widget, event, NULL, 0);
1175 else if (event->type == ButtonRelease)
1177 if (AB_btn1_transfer != True && move_in_progress) /* BUTTON2 TRANSFER */
1178 object_move_release(widget, client_data, event, cont_dispatch);
1180 object_toggle_select(widget, event, NULL, 0);
1185 if (event->type == ButtonPress)
1186 object_popup_menu(widget, event, NULL, 0);
1190 else if (event->type == MotionNotify)
1192 mevent = (XMotionEvent*)event;
1193 if (mevent->state & Button1Mask)
1195 /* Check to see if the drag occurred while we are waiting for hte
1196 * double-click interval to expire. If so, then if the drag is
1197 * outside the threshhold, cancel the double-click and initiate
1200 if (d_click->waiting)
1202 if (abs(mevent->x - d_click->start_x) > AB_drag_threshold ||
1203 abs(mevent->y - d_click->start_y) > AB_drag_threshold)
1205 XtRemoveTimeOut(timer_id);
1206 d_click->waiting = False;
1207 object_button_press(d_click->widget, d_click->event, NULL, 0);
1210 else /* call the generic drag event-handler to process the drag */
1211 object_button_drag(widget, client_data, event, cont_dispatch);
1213 else if (mevent->state & Button2Mask && AB_btn1_transfer != True)
1214 object_button_drag(widget, client_data, event, cont_dispatch);
1216 /* absorb all motion events */
1217 *cont_dispatch = False;
1222 * EventHandler: drag action ...
1227 XtPointer client_data,
1229 Boolean *cont_dispatch
1232 XMotionEvent *mevent;
1233 ABObj obj = (ABObj)client_data;
1236 if (event->type == MotionNotify)
1238 mevent = (XMotionEvent*)event;
1240 if (obj_is_item(obj))
1241 obj = obj_get_root(obj_get_parent(obj));
1243 if (mevent->state & Button1Mask ||
1244 (AB_btn1_transfer != True && mevent->state & Button2Mask))
1245 /* RESIZE, MOVE or RUBBERBAND-SELECT */
1247 if (resize_in_progress)
1249 abobjP_resize_object_outline(obj, event, resize_dir);
1251 else if (potential_move)
1253 /* If moving a Control within a Group, move the whole
1256 moveObj = obj_get_root(obj);
1257 while(obj_is_group(obj_get_root(obj_get_parent(moveObj))))
1258 moveObj = obj_get_root(obj_get_parent(moveObj));
1260 if (moveObj != obj_get_root(obj)) /* moveObj is translated to Group */
1263 int trans_x, trans_y;
1266 /* Translate obj/widget to be the Group */
1267 obj = objxm_comp_get_subobj(moveObj, AB_CFG_PARENT_OBJ);
1269 widget = objxm_get_widget(obj);
1271 /* Translate Control's x,y position relative to Group 0,0 */
1272 XTranslateCoordinates(XtDisplay(orig_w),
1273 XtWindow(orig_w), XtWindow(widget),
1274 mevent->x, mevent->y, &trans_x, &trans_y, &win);
1276 mevent->x = trans_x;
1277 mevent->y = trans_y;
1279 if (!move_in_progress) /* Initialize Move operation */
1281 if (!obj_is_selected(moveObj))
1282 object_select(widget, NULL, NULL, 0);
1284 if (initiate_move(widget, obj) == ERROR)
1286 move_in_progress = False;
1287 potential_move = False;
1288 util_dprintf(0, "object_select_drag: couldn't begin move\n");
1291 move_in_progress = True;
1293 abobjP_move_object_outline(obj, mevent);
1296 else if (mselect_in_progress) /* RUBBERBAND-SELECT */
1297 ui_button_drag(widget, event, (XtPointer)obj);
1299 else if (mevent->state & Button2Mask) /* RUBBERBAND-ADJUST */
1300 ui_button_drag(widget, event, (XtPointer)obj);
1306 * EventHandler: object move action is completed...
1310 object_move_release(
1312 XtPointer client_data,
1314 Boolean *cont_dispatch
1317 ABObj obj = (ABObj)client_data;
1319 if (event->type != ButtonRelease)
1322 if (move_in_progress)
1324 XtUngrabPointer(widget, CurrentTime);
1325 XtRemoveEventHandler(widget, ButtonReleaseMask, False,
1326 object_move_release, (XtPointer)obj);
1327 move_in_progress = False;
1330 abobj_move(obj, event);
1337 * EventHandler: object resize action is completed...
1338 * resize the object!
1341 object_resize_release(
1343 XtPointer client_data,
1345 Boolean *cont_dispatch
1348 ABObj obj = (ABObj)client_data;
1350 if (!resize_in_progress || event->type != ButtonRelease)
1353 XtUngrabPointer(widget, CurrentTime);
1354 XtRemoveEventHandler(widget, ButtonReleaseMask, False,
1355 object_resize_release, (XtPointer)obj);
1356 resize_in_progress = False;
1357 abobj_resize(obj, event);
1358 *cont_dispatch = False;
1366 XRectangle *rb_rect,
1367 XtPointer client_data
1374 ABSelectedRec old_sel, new_sel;
1377 XRectangle tmp_rect;
1380 if (!mselect_in_progress)
1383 obj = (ABObj)client_data;
1385 pobj = objxm_comp_get_subobj(obj, AB_CFG_PARENT_OBJ);
1386 num_controls = obj_get_num_children(pobj);
1387 new_sel.list = (ABObj*)util_malloc(num_controls*sizeof(ABObj));
1390 abobj_get_selected(obj_get_window(pobj), True, False, &old_sel);
1392 /* If rubberband was drawn from lower-right to upper-left,
1393 * translate rect so that x,y is upper-left point in rectangle.
1395 if (rect_right(rb_rect) < rb_rect->x ||
1396 rect_bottom(rb_rect) < rb_rect->y)
1398 tmp_rect.x = rect_right(rb_rect);
1399 tmp_rect.y = rect_bottom(rb_rect);
1400 tmp_rect.width = rb_rect->x - tmp_rect.x;
1401 tmp_rect.height = rb_rect->y - tmp_rect.y;
1402 rb_rect = &tmp_rect;
1405 for (i = 0; i < num_controls; i++)
1407 control = obj_get_child(pobj, i);
1409 if (obj_is_salient(control))
1411 xyobj = objxm_comp_get_subobj(control, AB_CFG_POSITION_OBJ);
1413 if (objxm_get_widget(xyobj) != NULL)
1415 x_get_widget_rect(objxm_get_widget(xyobj), &c_rect);
1417 if (rect_includesrect(rb_rect, &c_rect))
1420 * If RUBBERBAND-SELECT, deselect other currently selected
1422 * If RUBBERBAND-ADJUST, deselect only currently selected
1423 * NON-sibling objects
1425 if (old_sel.count > 0)
1427 for(j = 0; j < old_sel.count; j++)
1429 if (control != old_sel.list[j] &&
1431 !obj_is_sibling(control, old_sel.list[j])))
1432 abobj_deselect(old_sel.list[j]);
1436 new_sel.list[new_sel.count] = control;
1442 for (i=0; i < new_sel.count; i++)
1443 abobj_select(new_sel.list[i]);
1445 util_free(old_sel.list);
1446 util_free(new_sel.list);
1448 mselect_in_progress = mselect_adjust = False;
1455 XtPointer client_data,
1459 dtb_palette_prevent_close_msg_initialize(
1460 &dtb_palette_prevent_close_msg);
1461 dtb_show_message(widget, &dtb_palette_prevent_close_msg, NULL, NULL);
1467 XtPointer client_data,
1472 ABObj winobj = (ABObj)client_data;
1473 XConfigureEvent *cevent;
1475 if (event->type == ConfigureNotify)
1477 cevent = (XConfigureEvent*)event;
1478 winobj->x = cevent->x;
1479 winobj->y = cevent->y;
1484 object_track_iconify(
1486 XtPointer client_data,
1491 ABObj winobj = (ABObj)client_data;
1493 switch (event->type)
1497 * If this event is a result of the remap that occurs when
1498 * window decorations are changed going to/from Test mode, then
1499 * do not interpret it as a de-iconification.
1501 if (obj_has_flag(winobj, DecorChangedFlag))
1502 obj_clear_flag(winobj, DecorChangedFlag);
1505 * If this event is a result of the remap that occurs when
1506 * windows are maped exiting from Test mode, then do not
1507 * interpret it as a de-iconification.
1509 else if (obj_has_flag(winobj, TestModeWinFlag))
1510 obj_clear_flag(winobj, TestModeWinFlag);
1512 else if (InBuildMode &&
1513 obj_has_flag(winobj, IconifiedFlag) &&
1514 !ab_window_leader_iconified())
1516 obj_clear_flag(winobj, IconifiedFlag);
1517 XtVaSetValues(widget, XtNinitialState, NormalState, NULL);
1523 * If this event is a result of the unmap that occurs when
1524 * window decorations are changed going to/from Test mode, then
1525 * do not interpret it as an iconification.
1527 if (obj_has_flag(winobj, DecorChangedFlag))
1528 obj_clear_flag(winobj, DecorChangedFlag);
1531 * If this event is a result of the unmap that occurs when
1532 * windows are unmaped exiting from Test mode, then do not
1533 * interpret it as an iconification.
1535 else if (obj_has_flag(winobj, TestModeWinFlag))
1536 obj_clear_flag(winobj, TestModeWinFlag);
1538 else if (InBuildMode &&
1539 !obj_has_flag(winobj, IconifiedFlag) &&
1540 obj_has_flag(winobj, MappedFlag) &&
1541 !ab_window_leader_iconified())
1543 obj_set_flag(winobj, IconifiedFlag);
1544 XtVaSetValues(widget, XtNinitialState, IconicState, NULL);