| 1 | // =============================================================== // | 
|---|
| 2 | //                                                                 // | 
|---|
| 3 | //   File      : AW_cb_struct.cxx                                  // | 
|---|
| 4 | //   Purpose   :                                                   // | 
|---|
| 5 | //                                                                 // | 
|---|
| 6 | //   Institute of Microbiology (Technical University Munich)       // | 
|---|
| 7 | //   http://www.arb-home.de/                                       // | 
|---|
| 8 | //                                                                 // | 
|---|
| 9 | // =============================================================== // | 
|---|
| 10 |  | 
|---|
| 11 | #include "aw_root.hxx" | 
|---|
| 12 | #include "aw_window.hxx" | 
|---|
| 13 | #include "aw_window_Xm.hxx" | 
|---|
| 14 | #include "aw_msg.hxx" | 
|---|
| 15 |  | 
|---|
| 16 | #if defined(DEBUG) | 
|---|
| 17 | // #define TRACE_CALLBACKS | 
|---|
| 18 | #endif // DEBUG | 
|---|
| 19 |  | 
|---|
| 20 | AW_cb_struct_guard AW_cb::guard_before = NULp; | 
|---|
| 21 | AW_cb_struct_guard AW_cb::guard_after  = NULp; | 
|---|
| 22 | AW_postcb_cb       AW_cb::postcb       = NULp; | 
|---|
| 23 |  | 
|---|
| 24 |  | 
|---|
| 25 | AW_cb::AW_cb(AW_window *awi, const WindowCallback& wcb, const char *help_texti, class AW_cb *nexti) | 
|---|
| 26 | : cb(wcb) | 
|---|
| 27 | { | 
|---|
| 28 | aw         = awi; | 
|---|
| 29 | help_text  = help_texti; | 
|---|
| 30 | this->next = nexti; | 
|---|
| 31 |  | 
|---|
| 32 | id = NULp; | 
|---|
| 33 | } | 
|---|
| 34 |  | 
|---|
| 35 |  | 
|---|
| 36 | bool AW_cb::contains(AnyWinCB g) { | 
|---|
| 37 | return (AnyWinCB(cb.callee()) == g) || (next && next->contains(g)); | 
|---|
| 38 | } | 
|---|
| 39 |  | 
|---|
| 40 | bool AW_cb::is_equal(const AW_cb& other) const { | 
|---|
| 41 | bool equal = cb == other.cb; | 
|---|
| 42 | if (equal) { | 
|---|
| 43 | equal = aw == other.aw; | 
|---|
| 44 | if (!equal) { | 
|---|
| 45 | equal = aw->get_root() == other.aw->get_root(); | 
|---|
| 46 | #if defined(DEBUG) && 0 | 
|---|
| 47 | if (equal) { | 
|---|
| 48 | fprintf(stderr, | 
|---|
| 49 | "callback '%s' instantiated twice with different windows (w1='%s' w2='%s') -- assuming the callbacks are equal\n", | 
|---|
| 50 | id, aw->get_window_id(), other.aw->get_window_id()); | 
|---|
| 51 | } | 
|---|
| 52 | #endif // DEBUG | 
|---|
| 53 | } | 
|---|
| 54 | } | 
|---|
| 55 | return equal; | 
|---|
| 56 | } | 
|---|
| 57 |  | 
|---|
| 58 |  | 
|---|
| 59 | void AW_cb::run_callbacks() { | 
|---|
| 60 | if (next) next->run_callbacks();                // callback the whole list | 
|---|
| 61 |  | 
|---|
| 62 | AnyWinCB f = AnyWinCB(cb.callee()); | 
|---|
| 63 | aw_assert(f); | 
|---|
| 64 |  | 
|---|
| 65 | AW_root *root = aw->get_root(); | 
|---|
| 66 | if (root->disable_callbacks) { | 
|---|
| 67 | // some functions (namely aw_message, aw_input and aw_file_selection) | 
|---|
| 68 | // have to disable most callbacks, because they are often called from inside these callbacks | 
|---|
| 69 | // (e.g. because some exceptional condition occurred which needs user interaction) and if | 
|---|
| 70 | // callbacks weren't disabled, a recursive deadlock occurs. | 
|---|
| 71 |  | 
|---|
| 72 | // the following callbacks are allowed even if disable_callbacks is true | 
|---|
| 73 |  | 
|---|
| 74 | bool isModalCallback = (f == CASTSIG(AnyWinCB, message_cb) || | 
|---|
| 75 | f == CASTSIG(AnyWinCB, input_history_cb) || | 
|---|
| 76 | f == CASTSIG(AnyWinCB, input_cb)         || | 
|---|
| 77 | f == CASTSIG(AnyWinCB, file_selection_cb)); | 
|---|
| 78 |  | 
|---|
| 79 | bool isPopdown = (f == AnyWinCB(AW_POPDOWN)); | 
|---|
| 80 | bool isHelp    = (f == CASTSIG(AnyWinCB, AW_help_popup)); | 
|---|
| 81 | bool allow     = isModalCallback || isHelp || isPopdown; | 
|---|
| 82 |  | 
|---|
| 83 | bool isInfoResizeExpose = false; | 
|---|
| 84 |  | 
|---|
| 85 | if (!allow) { | 
|---|
| 86 | isInfoResizeExpose = aw->is_expose_callback(AW_INFO_AREA, f) || aw->is_resize_callback(AW_INFO_AREA, f); | 
|---|
| 87 | allow              = isInfoResizeExpose; | 
|---|
| 88 | } | 
|---|
| 89 |  | 
|---|
| 90 | if (!allow) { | 
|---|
| 91 | // do not change position of modal dialog, when one of the following callbacks happens - just raise it | 
|---|
| 92 | // (other callbacks like pressing a button, will position the modal dialog under mouse) | 
|---|
| 93 | bool onlyRaise = | 
|---|
| 94 | aw->is_expose_callback(AW_MIDDLE_AREA, f) || | 
|---|
| 95 | aw->is_focus_callback(f) || | 
|---|
| 96 | aw->is_resize_callback(AW_MIDDLE_AREA, f); | 
|---|
| 97 |  | 
|---|
| 98 | if (root->current_modal_window) { | 
|---|
| 99 | AW_window *awmodal = root->current_modal_window; | 
|---|
| 100 |  | 
|---|
| 101 | AW_PosRecalc prev = awmodal->get_recalc_pos_atShow(); | 
|---|
| 102 | if (onlyRaise) awmodal->recalc_pos_atShow(AW_KEEP_POS); | 
|---|
| 103 | awmodal->activate(); | 
|---|
| 104 | awmodal->recalc_pos_atShow(prev); | 
|---|
| 105 | } | 
|---|
| 106 | else { | 
|---|
| 107 | aw_message("Internal error (callback suppressed when no modal dialog active)"); | 
|---|
| 108 | aw_assert(0); | 
|---|
| 109 | } | 
|---|
| 110 | #if defined(TRACE_CALLBACKS) | 
|---|
| 111 | printf("suppressing callback %p\n", f); | 
|---|
| 112 | #endif // TRACE_CALLBACKS | 
|---|
| 113 | return; // suppress the callback! | 
|---|
| 114 | } | 
|---|
| 115 | #if defined(TRACE_CALLBACKS) | 
|---|
| 116 | else { | 
|---|
| 117 | if (isModalCallback) printf("allowed modal callback %p\n", f); | 
|---|
| 118 | else if (isPopdown) printf("allowed AW_POPDOWN\n"); | 
|---|
| 119 | else if (isHelp) printf("allowed AW_help_popup\n"); | 
|---|
| 120 | else if (isInfoResizeExpose) printf("allowed expose/resize infoarea\n"); | 
|---|
| 121 | else printf("allowed other (unknown) callback %p\n", f); | 
|---|
| 122 | } | 
|---|
| 123 | #endif // TRACE_CALLBACKS | 
|---|
| 124 | } | 
|---|
| 125 | else { | 
|---|
| 126 | #if defined(TRACE_CALLBACKS) | 
|---|
| 127 | printf("Callbacks are allowed (executing %p)\n", f); | 
|---|
| 128 | #endif // TRACE_CALLBACKS | 
|---|
| 129 | } | 
|---|
| 130 |  | 
|---|
| 131 | useraction_init(); | 
|---|
| 132 | cb(aw); | 
|---|
| 133 | useraction_done(aw); | 
|---|
| 134 | } | 
|---|