Sharing an input queue takes what used to be asynchronous and makes it synchronous, like focus changes


As I noted earlier in the series, attaching input queues puts you back into the world of coöperative multitasking, where the two attached threads need to work together to get anything done.

Back in the old 16-bit days, when input was synchronous, there was only one active window, only one focus window, only one window with capture, only one caret, only one cursor show count, only one keyboard state, only one input state. Furthermore, if you called Set­Focus, you had to wait until the previous focus window responded to the WM_KILL­FOCUS message before your Set­Focus call returned.

With asynchronous input, these sorts of operations are now local to your input queue. If you call Set­Focus, then that steals focus only from other windows which belong to your input queue. Windows which belong to other input queues are unaffected. (Conversely, you can set focus only to windows which belong to your input queue, since those are the only windows your input queue has access to.)

This is probably not very exciting, until you look at the one thing that can reach across input queues: The foreground window.

The concept of the foreground window was introduced when input was desynchronized in order to express the “really global active window”, as opposed to Set­Active­Window, which continued to refer to the local active window. It’s something that was originally intended to be used only in emergencies since it violates the isolation of input queues, but as we learned before, eventually nothing is special any more, and what used to be the special function for stepping outside the box has become the function you use every day for getting things done.

What most people don’t realize is that Set­Foreground­Window is still subject to the rules on synchronous input. If you call Set­Foreground­Window, and the previous foreground window also belongs to your input queue, then your call to Set­Foreground­Window will wait until the previous foreground window processes its WM_ACTIVATE(WA_INACTIVE) message.

A lot of people use Attach­Thread­Input thinking that it’s a Get Out of Jail Free card, letting them manipulate windows of other programs and bypass the normal rules for focus and activation. But in fact it’s a Get Into the Same Jail card, because you tied your thread’s fate to that other thread. If that thread has stopped responding to messages, then your thread will also stop responding to messages, since you are sharing the same input queue and operations within an input queue are synchronous.

Bonus reminder: If two windows are related by a parent/child relationship or owner/owned relationship, then their input queues are automatically attached. For example, if you do a Set­Parent where the parent and child are in different threads, you have just synchronized the two threads. This sort of cross-thread relationship is technically legal, but it is very difficult to manage correctly, so it should be avoided unless you really know what you’re doing. And if you are doing cross-thread or cross-process between windows that were not designed to participate in cross-thread or cross-process parenting, you are almost certainly doomed.

Comments (19)
  1. This is also the reason that GetForegroundWindow can return nullptr, I believe.

  2. Yuri says:

    Would usage of Attach­Thread­Input function be recommended for UI plugins use case?

  3. @Yuri says:

    [If you are doing cross-thread or cross-process between windows that were not designed to participate … you are almost certainly doomed.]

    So in general: No.

  4. Myria says:

    I'm always amazed at how often people want to mess with other processes that are not designed for it, or are even made by third parties.  Often, the developers even want to put such tricks into production applications.

    I do reverse engineering on occasion – I definitely have messed with applications that don't like to be messed with (malware, for example), so I know various ways of modifying the operation of other programs.  But really, such techniques should only be used by debugging tools or highly-specialized system information tools.  Process separation exists for a reason, and applications would be more stable and compatible if they kept more to themselves.  Your application is not special.

  5. Mark Y. says:

    Forgive the off topic question, but how do you (personally) type the accented "o" in cooperative?

  6. Kevin says:

    @Mark Y. Press the compose key, then press ", then press o (don't try to hold any of those keys down).  You get 'ö'.

    What, you don't have a compose key?  Well, just Google "O with umlaut" (even though that's actually a diaeresis) and copy/paste.

  7. voo says:

    @Kevin: I thought you just press the ö key on your keyboard? Ah yes right I'm in Europe right now that's why that works ;) For everybody else ALT+0246 also works (though that's in my experience the first thing everybody gives up, true at least for Germans, French and Spanish people)

  8. j b says:

    My question is rather where that "ö" in "coöperative" comes from – whether it belongs there at all.

    Usually, "umlauts" (or any modification of a vowel sound) comes in conjugations or other modifications of a base form. (In English it isn't always reflected in spelling of the vowel sound, such as child/children, woman/women, but it's the same phenomenon.) But there is no vowel sound modification from "operative" to "cooperative", so why the change in spelling? Or would you spell it "öperative" ("öperation", "öperate", …) and as well?

    (For those unfamiliar with the "ö": In West European languages using it as a plain vowel, it is pronounced somwehat like the opening vowel sound of "up". I never heard any native English speaker pronounce "cooperative" like "co-upperative".)

  9. Ramon Beiboer says:

    @j b: The "ö" in "coöperative" has a diaeresis on top of it, not an umlaut (although they look the same). It is very common in the Dutch language for instance. See en.wikipedia.org/…/Diaeresis_(diacritic) for its usage.

  10. JM says:

    @Ramon: although, in Dutch, non-technical speakers often call the diaeresis an umlaut anyway (or, even more commonly, "dots" — which, though prosaic, has the benefit of being not technically incorrect). The proper Dutch term for the diaeresis is "trema". There's no real confusion since Dutch itself has no umlaut, except in German loanwords (most prominently "überhaupt").

    Use of the diaeresis in English is rare, almost archaic. It's certainly pointless — orthographically, English is too far gone to offer pronunciation hints in diacritics.

  11. DWalker59 says:

    Still off-topic, but … even though we think that American English has 26 letters in the alphabet, older writing will have (sorry for the discomfort) words like "diarrhoea" where the o and e are combined into one letter.  Perhaps that's "chiefly British", but it's certainly not one of the 26 letters… along with ö.

    I disagree that the diaeresis in English is pointless.  Some magazines print coöperate as a matter of course, and I think it's helpful.

  12. Nick says:

    The diaeresis in English shows the second vowel is pronounced separately, not as part of a dipthong. So "coöp" discusses people or things that work together while "coop" is the place where chickens live (this is overly simplified but basically true).

  13. jim says:

    Raymond needs to form a heavy metal band called Coöperative Mültitäsking.

  14. JM says:

    @DWalker: if there were ever a reasonable case for "cooperate" with the "oo" pronounced as one vowel, you'd have a point. There is no ambiguity; there might be a slight benefit to non-native speakers but even that is dubious (given that pronouncing "cooperate" from spelling will probably be the least of their worries).

    In the rare case where there is ambiguity (Nick's coöp versus coop) I don't know why anyone wouldn't just use a hyphen and write it "co-op", which has the benefit of avoiding potential encoding issues with the diaeresis. Even so "co-operate" would be overkill since there is no other way to read "cooperate" (except, again, if you don't know the language).

    Since the diaeresis is the only native diacritic English has left I can see why people would cling to it, but it's still a relic.

  15. j b says:

    Ramon Beiboer,

    "Umlaut" and "diaresis" are really two sides of the same coin. "Diaresis" is the graphical indicator, "umlaut" is the effect (roughly speaking: "changed sound"). In my native language, Norwegian, "omlyd" can be indicated in writing in various accents or change of vowel (e.g. "tann"/"tenner" – tooth/teeth); not restricted to diaresis. In German, diaresis is by far the most common way to indicate an umlaut (and that is what the diaresis is used for, nothing else that I know of), so "umlaut" has become the common way to refer to the two dots. ("Diaresis" doesn't sound "at home" in the German language!)

    Worth mentioning: In Norwegian (and Danish), ö originally was an o umlaut, but has for about a hundred years been replaced with a slashed o ("ø") which is used in lots of words as an "independent" vowel – that is, not an umlaut. Many words are written with an ø in its base, unconjugated, form. Similarly, the ä (a diaresis) has been an independent vowel ("æ") for just as long. In Swedish, however, ö and ä (more or less interchangeable with the Norwegian/Danish ø and æ) are still written with diaresis, yet treated as independent vowels – e.g. they are sorted at the end of the alphabet, not as their "base character" …but not in the same order as in Danish or Norwegian… (The Swedes go å, ä. ö, while we go æ, ø, å) …The good things about standards, and so on. We all know that one.

  16. j b says:

    Nick,

    > The diaeresis in English shows the second vowel is pronounced separately, not as part of a dipthong.

    That explanation makes sense, and even more if you think of the use of e.g. i diaresis (ï) in words like 'naïve', where is serves a similar purpose: To indicate that "ai" is not a diphtong. For "co-operative" a hyphen could be (and often is) used for the same purpose, but you never write "na-ive".

    In German-related languages (like the Nordic ones) we never use ï (i diaresis) in the official spelling. You _might_ encounter "naïv"; we sor of accept the 'Latin' spelling but think of it as a mixture of some writer pretending to be An Intellectual :-) and someone who thinks it necessary to help the first-time reader of the word to learn its pronounciation. We explain it as "a long 'eee' sound" – just as we explain the circonflex accent on "fôr" (fodder) as "a long oooo sound" to distinguish it from "for", the preposition.

    Official spelling omits both the diaresis in "naive" and the circonflex on "for". You are supposed to deduce both meaning and correct pronounciation from context – which happens to be far easier in Norwegian than in English. For those who do not know "English is tough stuff", look up, and read out loud, appliedabstractions.com/…/english-is-tough-stuff (it is found at dozens of other sites as well).

  17. Myria says:

    It is naïve to assume that English entirely can be written without diacritics.

  18. j b says:

    @j b: (Still off-topic here, sorry Raymond!) Well, maybe I am using the wrong English term here (I'm not English, I'm Dutch so forgive me). What I meant to say is that the diaeresis (the two dots) can have two meanings: the umlaut (changing the way the vowel is pronounced) and the 'trema'. The first one is only used in Dutch in words taken from other languages, like German (überhaupt, see JM's comment). The trema is used more often and has a different effect. The Dutch translation of diaeresis is a goog example of it: diëresis. The trema (or  diëresis) is placed on the first 'e' to indicate that the 'ie' is not proncounced as one sound, but as two seperate sounds 'i' and 'e' (in the Dutch language we have a special sound for 'ie', 'eu', 'oe' and more of these two-vowel combinations). And the separation is also the case for the English word 'coöoperation'. But you are right about the umlaut and it's usage in German and Danish and Norwegian :)

  19. Ramon Beiboer says:

    Sorry, the previous post of 'j b' was mine! I accidentally filled in your name instead of mine! I treated it like an e-mail program I guess ;)

Comments are closed.