| 23 | |
| 24 | |
| 25 | bool MsgSleep(int aSleepDuration, MessageMode aMode) |
| 26 | // Returns true if it launched at least one thread, and false otherwise. |
| 27 | // aSleepDuration can be be zero to do a true Sleep(0), or less than 0 to avoid sleeping or |
| 28 | // waiting at all (i.e. messages are checked and if there are none, the function will return |
| 29 | // immediately). aMode is either RETURN_AFTER_MESSAGES (default) or WAIT_FOR_MESSAGES. |
| 30 | // If the caller doesn't specify aSleepDuration, this function will return after a |
| 31 | // time less than or equal to SLEEP_INTERVAL (i.e. the exact amount of the sleep |
| 32 | // isn't important to the caller). This mode is provided for performance reasons |
| 33 | // (it avoids calls to GetTickCount and the TickCount math). However, if the |
| 34 | // caller's script subroutine is suspended due to action by us, an unknowable |
| 35 | // amount of time may pass prior to finally returning to the caller. |
| 36 | { |
| 37 | bool we_turned_on_defer = false; // Set default. |
| 38 | if (aMode == RETURN_AFTER_MESSAGES_SPECIAL_FILTER) |
| 39 | { |
| 40 | aMode = RETURN_AFTER_MESSAGES; // To simplify things further below, eliminate the mode RETURN_AFTER_MESSAGES_SPECIAL_FILTER from further consideration. |
| 41 | // g_DeferMessagesForUnderlyingPump is a global because the instance of MsgSleep on the call stack |
| 42 | // that set it to true could launch new thread(s) that call MsgSleep again (i.e. a new layer), and a global |
| 43 | // is the easiest way to inform all such MsgSleeps that there's a non-standard msg pump beneath them on the |
| 44 | // call stack. |
| 45 | if (!g_DeferMessagesForUnderlyingPump) |
| 46 | { |
| 47 | g_DeferMessagesForUnderlyingPump = true; |
| 48 | we_turned_on_defer = true; |
| 49 | } |
| 50 | // So now either we turned it on or some layer beneath us did. Therefore, we know there's at least one |
| 51 | // non-standard msg pump beneath us on the call stack. |
| 52 | } |
| 53 | |
| 54 | // While in mode RETURN_AFTER_MESSAGES, there are different things that can happen: |
| 55 | // 1) We launch a new hotkey subroutine, interrupting/suspending the old one. But |
| 56 | // subroutine calls this function again, so now it's recursed. And thus the |
| 57 | // new subroutine can be interrupted yet again. |
| 58 | // 2) We launch a new hotkey subroutine, but it returns before any recursed call |
| 59 | // to this function discovers yet another hotkey waiting in the queue. In this |
| 60 | // case, this instance/recursion layer of the function should process the |
| 61 | // hotkey messages linearly rather than recursively? No, this doesn't seem |
| 62 | // necessary, because we can just return from our instance/layer and let the |
| 63 | // caller handle any messages waiting in the queue. Eventually, the queue |
| 64 | // should be emptied, especially since most hotkey subroutines will run |
| 65 | // much faster than the user could press another hotkey, with the possible |
| 66 | // exception of the key-repeat feature triggered by holding a key down. |
| 67 | // Even in that case, the worst that would happen is that messages would |
| 68 | // get dropped off the queue because they're too old (I think that's what |
| 69 | // happens). |
| 70 | // Based on the above, when mode is RETURN_AFTER_MESSAGES, we process |
| 71 | // all messages until a hotkey message is encountered, at which time we |
| 72 | // launch that subroutine only and then return when it returns to us, letting |
| 73 | // the caller handle any additional messages waiting on the queue. This avoids |
| 74 | // the need to have a "run the hotkeys linearly" mode in a single iteration/layer |
| 75 | // of this function. Note: The WM_QUIT message does not receive any higher |
| 76 | // precedence in the queue than other messages. Thus, if there's ever concern |
| 77 | // that that message would be lost, as a future change perhaps can use PeekMessage() |
| 78 | // with a filter to explicitly check to see if our queue has a WM_QUIT in it |
| 79 | // somewhere, prior to processing any messages that might take result in |
| 80 | // a long delay before the remainder of the queue items are processed (there probably |
| 81 | // aren't any such conditions now, so nothing to worry about?) |
| 82 |
no test coverage detected