/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these libraries and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /* * $XConsortium: tmode.c /main/3 1995/11/06 17:54:31 rswiston $ * * @(#)tmode.c 1.2 17 Jan 1995 cde_app_builder/src/ab * * RESTRICTED CONFIDENTIAL INFORMATION: * * The information in this document is subject to special * restrictions in a confidential disclosure agreement between * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this * document outside HP, IBM, Sun, USL, SCO, or Univel without * Sun's specific written approval. This document and all copies * and derivative works thereof must be returned or destroyed at * Sun's request. * * Copyright 1993 Sun Microsystems, Inc. All rights reserved. * */ /* ** File: tmode.c - *New* Test Mode interface */ #include "tmode.h" #include "tmodeP.h" #include #include #include #include #include #ifdef DEBUG /* performance testing */ #include typedef struct { double startSeconds; double endSeconds; double elapsedSeconds; } ABTimedIntervalRec, *ABTimedInterval; typedef struct { ABTimedIntervalRec realTime; ABTimedIntervalRec CPUTime; } ABProfiledIntervalRec, *ABProfiledInterval; static int get_cur_times(double *realTimeOut, double *cpuTimeOut); static int get_start_times(ABProfiledInterval); static int get_end_times(ABProfiledInterval); static int calc_elapsed_times(ABProfiledInterval); static int print_startup_time(ABProfiledInterval totalTime); static ABProfiledIntervalRec startupTime; #endif /* DEBUG/performance */ /***************************************************************************** ** ** ** Private Function Declarations ** ** ** *****************************************************************************/ static void win_get_geometry( ABObj obj ); static void track_win_focus( Widget widget, XtPointer client_data, XEvent *event, Boolean *cont_disp ); static void hide_windows( ABObj obj ); static void check_win_for_resize( ABObj obj ); static void cleanup_window( ABObj obj ); /***************************************************************************** ** ** ** Public Function Definitions ** ** ** *****************************************************************************/ /* ** Enable Test Mode ** ** This is the entry point into Test Mode. It setups up the book keeping ** structures necessary, and prepairs for the interpretation of connections. */ void tmode_enable( ABObj project, BOOL test_project ) { if (!project || !obj_is_project(project)) return; ab_set_busy_cursor(TRUE); util_dprintf(1, "\ntmode_enable\n"); #ifdef DEBUG /* performance testing */ get_start_times(&startupTime); #endif /* DEBUG */ /* store whether we are testing the whole project or not */ if (test_project) tmodeP_obj_set_flags(project, TestModeTestProject); /* create a list of the windows within the project */ if (tmodeP_window_list_create(project) != OK) { util_dprintf(1, "tmode_enable: Unable to create window list for Test Mode.\n"); goto cret; } /* get the current dimensions of the windows */ tmodeP_window_list_iterate(win_get_geometry); /* ** Attach a focus handler to each window in the project. When the window ** receives focus, it gets marked dirty. */ if (tmodeP_window_list_add_handler(EnterWindowMask, False, track_win_focus) != OK) { util_dprintf(1, "tmode_enable: Unable to add window focus handler.\n"); goto cret; } /* initialize the old interface */ conn_test_mode_initialize(project); conn_enable_action_interpret(project, test_project); cret: #ifdef DEBUG /* performance testing */ get_end_times(&startupTime); print_startup_time(&startupTime); #endif /* DEBUG */ ab_set_busy_cursor(FALSE); } /* ** Disable Test Mode ** ** This is the exit point for Test Mode. */ void tmode_disable( ABObj project ) { ABObj mod; AB_TRAVERSAL trav; if (!project || !obj_is_project(project)) return; ab_set_busy_cursor(TRUE); util_dprintf(1, "\ntmode_disable\n"); #ifdef DEBUG /* performance testing */ get_start_times(&startupTime); #endif /* DEBUG */ tmodeP_window_list_iterate(check_win_for_resize); /* process for resize */ tmodeP_window_list_iterate(hide_windows); /* rm not needed or resized */ conn_disable_action_interpret(project); conn_test_mode_cleanup(project); tmodeP_window_list_iterate(cleanup_window); /* re-instantiate/set_ui_args */ /* make sure windows are Mapped correctly */ for (trav_open(&trav, project, AB_TRAV_MODULES); (mod = trav_next(&trav)) != NULL; ) if (obj_is_module(mod)) { if (obj_has_flag(mod, MappedFlag)) objxm_tree_map(mod, TRUE); else objxm_tree_map(mod, FALSE); } trav_close(&trav); /* detach the receive focus handler */ if (tmodeP_window_list_remove_handler(EnterWindowMask, False, track_win_focus) != OK) { util_dprintf(1, "tmode_disable: Unable to remove window focus handler.\n"); goto cret; } /* destroy the window list */ if (tmodeP_window_list_destroy() != OK) util_dprintf(1, "tmode_disable: Problems destroying window list.\n"); tmodeP_obj_construct_flags(project); cret: #ifdef DEBUG /* performance testing */ get_end_times(&startupTime); print_startup_time(&startupTime); #endif /* DEBUG */ ab_set_busy_cursor(FALSE); } /***************************************************************************** ** ** ** Private Function Definitions ** ** ** *****************************************************************************/ #ifdef DEBUG /* performance testing */ static int get_start_times(ABProfiledInterval interval) { return get_cur_times(&(interval->realTime.startSeconds), &(interval->CPUTime.startSeconds)); } static int get_end_times(ABProfiledInterval interval) { return get_cur_times(&(interval->realTime.endSeconds), &(interval->CPUTime.endSeconds)); } static int calc_elapsed_times(ABProfiledInterval interval) { interval->realTime.elapsedSeconds = interval->realTime.endSeconds - interval->realTime.startSeconds; interval->CPUTime.elapsedSeconds = interval->CPUTime.endSeconds - interval->CPUTime.startSeconds; return 0; } static int print_startup_time(ABProfiledInterval totalTime) { /* * Print out statistics about load */ calc_elapsed_times(totalTime); fprintf(stderr, "Transition Time (Real/CPU) seconds: "); fprintf(stderr, "(%lg/%lg)\n", totalTime->realTime.elapsedSeconds, totalTime->CPUTime.elapsedSeconds); return 0; } static int get_cur_times(double *realTimeOut, double *cpuTimeOut) { static BOOL initialized = FALSE; static long ticks_per_second = 1; struct tms timeInfo; double realTime; double cpuTime; if (!initialized) { initialized = TRUE; ticks_per_second = sysconf(_SC_CLK_TCK); } realTime = times(&timeInfo); cpuTime = timeInfo.tms_utime + timeInfo.tms_stime + timeInfo.tms_cutime + timeInfo.tms_cstime; *realTimeOut = realTime / ticks_per_second; *cpuTimeOut = cpuTime / ticks_per_second; return 0; } #endif /* DEBUG/performance */ /* ** Record the window geometry */ static void win_get_geometry( ABObj obj ) { XRectangle rect; if (!obj || !obj->ui_handle) return; /* make sure there is a test mode data structure */ if (!tmodeP_obj_has_data(obj)) { if (tmodeP_obj_create_data(obj) != OK) { util_dprintf(2, "win_get_geometry: Unable to create test mode data.\n"); return; } } x_get_widget_rect(objxm_get_widget(obj), &rect); tmodeP_obj_set_geometry(obj, rect); } /* ** Track when a window receives focus and mark the window dirty */ static void track_win_focus( Widget widget, XtPointer client_data, XEvent *event, Boolean *cont_dispatch ) { ABObj obj = (ABObj) client_data; if (event->type == EnterNotify) { /* mark it dirty */ tmodeP_obj_set_flags(obj, TestModeFlagDirtyWindow); /* it's dirty, so no need to track it anymore */ XtRemoveEventHandler( widget, /* Widget */ EnterWindowMask, /* EventMask */ False, /* non-maskable events - Boolean */ track_win_focus, /* XtEventHandler */ (XtPointer) obj /* client_data */ ); } } /* ** If the module this window is associated with is hidden (in Build Mode) ** unmap it. Don't worry about unmapping the window's tree, that will be ** performed as one of the last steps in tmode_disable. */ static void hide_windows( ABObj obj ) { Widget widget; BOOL hide = FALSE; if (!obj || !obj->ui_handle) return; /* if the module will be hidden, unmap the windows associated w/it */ if (!obj_has_flag(obj_get_module(obj), MappedFlag)) if (obj_has_flag(obj, MappedFlag)) hide = TRUE; /* if the window is dirty or was resized, hide it to avoid uglyness */ if (tmodeP_obj_has_flags(obj, TestModeFlagDirtyWindow | TestModeFlagResizedWindow)) hide = TRUE; if (hide) { widget = (Widget)obj->ui_handle; util_dprintf(2,"UN-MAPPING widget: %s\n", util_strsafe(obj_get_name(obj))); if (XtIsSubclass(widget, applicationShellWidgetClass) || XtIsSubclass(widget, topLevelShellWidgetClass) || XtIsSubclass(widget, xmDialogShellWidgetClass)) { XtPopdown(widget); obj_clear_flag(obj, MappedFlag); } /* * Since we need to unmap/remap the window in order to hide * re-instantiations and set-args, we need to mark this window * object so that when the iconify_tracker, object_track_iconify(), * event handler is called, it doesn't interpret the Unmap event as * an iconify. (this is an unfortunate hack to get around the * mysterious problem of the Unmap event occurring AFTER we return * to BUILD mode). */ obj_set_flag(obj, TestModeWinFlag); } } /* ** Check if the window has been resized. If so, mark dirty. */ static void check_win_for_resize( ABObj obj ) { XRectangle rect; Boolean resized = False; if (!obj || !obj->ui_handle) return; /* compair current values with those stored on entry into Test Mode */ if (tmodeP_obj_has_data(obj)) { x_get_widget_rect(objxm_get_widget(obj), &rect); /* if width or height has changed, it's been resized */ if (rect.width != tmodeP_obj_get_width(obj)) resized = True; else if (rect.height != tmodeP_obj_get_height(obj)) resized = True; /* if resized, mark dirty */ if (resized) tmodeP_obj_set_flags(obj, TestModeFlagResizedWindow); } } /* ** Cleanup the window -- If the window was resized, there is no easy way to ** reconfigure it and make sure all of the widgets are proper; so, ** destroy its widgets and re-instantiate. If the window was not ** resized, but just fiddled with (Dirty); set all of the widgets ** back to their original values (as defined in the obj structure). */ static void cleanup_window( ABObj obj ) { if (!obj || !obj->ui_handle || !tmodeP_obj_flags(obj)) return; if (tmodeP_obj_has_flags(obj, TestModeFlagResizedWindow)) { /* destroy */ objxm_tree_uninstantiate(obj, True); /* re-instantiate */ abobj_instantiate_tree(obj, True); } else if (tmodeP_obj_has_flags(obj, TestModeFlagDirtyWindow)) { BOOL new; /* ** Reset the UI Args on the windows tree */ objxm_tree_remove_ui_args(obj, OBJXM_CONFIG_BUILD); objxm_tree_set_ui_args(obj, OBJXM_CONFIG_BUILD, TRUE); objxm_tree_instantiate_changes(obj, &new); objxm_tree_remove_ui_args(obj, OBJXM_CONFIG_BUILD); } }