| 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 | } |
|---|