{"id":18983774,"url":"https://github.com/dechamps/rudewindowfixer","last_synced_at":"2025-10-17T19:25:30.743Z","repository":{"id":45768759,"uuid":"455686978","full_name":"dechamps/RudeWindowFixer","owner":"dechamps","description":"Fix Windows taskbar always-on-top issues","archived":false,"fork":false,"pushed_at":"2023-01-31T22:31:31.000Z","size":2015,"stargazers_count":120,"open_issues_count":5,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-16T17:29:06.125Z","etag":null,"topics":["desktop","taskbar","win32","window-management","window-manager","windows"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dechamps.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-02-04T20:27:31.000Z","updated_at":"2025-04-12T14:53:23.000Z","dependencies_parsed_at":"2025-04-16T13:34:46.453Z","dependency_job_id":"ae9e7ca4-d1e1-4e84-a231-c60a8f511602","html_url":"https://github.com/dechamps/RudeWindowFixer","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dechamps%2FRudeWindowFixer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dechamps%2FRudeWindowFixer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dechamps%2FRudeWindowFixer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dechamps%2FRudeWindowFixer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dechamps","download_url":"https://codeload.github.com/dechamps/RudeWindowFixer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249788234,"owners_count":21325696,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["desktop","taskbar","win32","window-management","window-manager","windows"],"created_at":"2024-11-08T16:18:29.191Z","updated_at":"2025-10-17T19:25:25.684Z","avatar_url":"https://github.com/dechamps.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RudeWindowFixer: fix Windows taskbar always-on-top issues\n*Brought to you by [Etienne Dechamps][] - [GitHub][]*\n\n**If you are looking for executables, see the [GitHub releases page][].**\n\n## Description\n\nEver felt frustrated by this?\n\n![Taskbar bug screencap](taskbarbug.gif)\n\n**RudeWindowFixer is a small program that gets rid of known \"Windows taskbar not\nalways on top\" bugs.**\n\nSpecifically, it works around proven bugs in the internal Windows taskbar code\nwhere, under very specific circumstances, Windows mistakenly believes that you\nare using a full screen application and hides the taskbar.\n\n## Usage\n\n1. Download `RudeWindowFixer.exe` from the [GitHub releases page][].\n2. Run `RudeWindowFixer.exe`.\n   - Nothing will happen at first; this is normal. RudeWindowFixer is quietly\n     running in the background. You can check in the Task Manager if you want to\n     make sure.\n3. That's it!\n   - You will likely want to make `RudeWindowFixer.exe` [run on startup][] so\n     that it persists across reboots.\n4. Upvote this [Microsoft bug report][] to hopefully get Microsoft to prioritize\n   fixing the underlying Windows bug, which is described in detail below.\n\n## Limitations\n\nRudeWindowFixer does not claim to fix *all* possible taskbar always-on-top bugs.\nSadly, reverse engineering efforts (see below) revealed that the relevant\nWindows code paths are somewhat brittle and might be prone to variations on\nthese problems (e.g. different triggers or problematic window state) that\nRudeWindowFixer might not be able to detect and fix.\n\nAlso note that all investigation and testing was done on Windows 11 21H2\n22000.434; other Windows versions might behave differently.\n\nIf you notice that RudeWindowFixer does not fix the problem for you, or at least\nnot consistently, do feel free to [file an issue][] - it might be possible to\n[instrument your system](TRACING.md) to gather detailed data about your problem,\nespecially if you can reliably trigger it.\n\nIt's also theoretically possible that RudeWindowFixer could go overboard and\nmake the taskbar show up in cases where it shouldn't - namely, on top of full\nscreen applications (video players, games). This is unlikely to happen in\npractice. If you've seen it happen, do [file an issue][] and make sure to\nmention the name of the full screen application the taskbar is being shown on\ntop of.\n\n## Specific known issues that RudeWindowFixer does NOT fix\n\n- In [issue #3][issue3], it was discovered that Microsoft introduced a\n  regression in Windows 11 build 22000.556 ([KB5011493][]). The bug is not\n  present in build 22000.493. It appears that Microsoft has fixed it with the\n  22H2 update, around build 22621.1105.\n  - One known reproducer for this bug is:\n    1. Open the Start Menu.\n    2. Switch to any window using a taskbar window button.\n    3. Click anywhere *at the exact moment* the taskbar finishes its hiding\n       animation (assuming it's set to autohide).\n       - The timing is somewhat tight so this might require a few attempts.\n  - This is likely the issue that this [Feedback hub\n    entry](https://aka.ms/AAg7dw5) is about.\n  - This bug seems is completely unrelated to the other issues RudeWindowFixer\n    is fixing (see below) - in fact it doesn't seem to involve the Rude Window\n    Manager at all.\n- RudeWindowFixer currently does not address the [problem][issue4] of an app\n  being treated as full screen if its dimensions exceed those of the monitor,\n  leading the taskbar to drop behind it.\n\n## The problems in detail\n\n_**Disclaimer:** The following information was gathered through careful\ninstrumentation of various window management facilities as well as [reverse\nengineering][] (disassembly) of the relevant Windows code, helped by [public\nMicrosoft symbols][]. Reverse engineering is a difficult task where quick\nprogress requires a fair amount of guesswork, so I wouldn't assume all the\ndetails below are exactly correct. This information applies to Windows 11 21H2\n22000.434. The behaviour of other Windows versions might differ._\n\n### TL;DR\n\nThere are two known scenarios in which the taskbar can accidentally lose its\n\"always on top\" status. The following background information is required to\nunderstand both:\n\n- The taskbar \"always on top\" window property is controlled by a piece of\n  internal Windows code called the *Rude Window Manager*.\n- The Rude Window Manager will only make the taskbar \"always on top\" on a given\n  monitor if, among the windows located on that monitor, the top (foreground)\n  window is not a full screen window.\n- Some applications create *transparent* full screen windows that are\n  essentially invisible, but still count as full screen windows as far as the\n  Rude Window Manager is concerned.\n\nThe first failure mode is fairly simple: it is triggered by the presence of an\n*always on top* transparent full screen window. This essentially confuses the\nRude Window Manager, resulting in the taskbar \"always on top\" property being\ndropped.\n\nThe second failure mode is more subtle and harder to trigger, but does not\nrequire the transparent full screen window to be always on top:\n\n- A minimized window is not \"located on\" any monitor and is therefore never seen\n  as the \"top\" window by the Rude Window Manager.\n- When a minimized window is activated, a race condition can occur wherein the\n  Rude Window Manager still sees the window as minimized and therefore does not\n  treat it as the new \"top\" window.\n- If the next window located on that monitor happens to be a (possibly\n  transparent) full screen window, the Rude Window Manager will wrongly conclude\n  that a full screen window is on top, and wrongly drop the taskbar \"always on\n  top\" property.\n\nThe rest of this section go into each of these points in more detail.\n\n### Taskbar \"always on top\" behavior\n\nDuring normal usage, the Windows taskbar is \"always on top\" of other windows.\nMore specifically, the taskbar window (`Shell_TrayWnd` window class, part of\n`explorer.exe`) has the `WS_EX_TOPMOST` [extended window style][].\n\nHowever, there is a case where Windows will drop the \"always on top\" property\nand will put the taskbar behind all other windows. This happens when Windows\nbelieves the user is interacting with a full screen application. This prevents\nthe taskbar from obscuring the full screen application.\n\n### The Rude Window Manager\n\nIn internal Windows code, this full screen detection logic is implemented in an\ninternal class called the *rude window manager*\n(`twinui!CGlobalRudeWindowManager`, also running in `explorer.exe`). Internally,\nthe code uses the term *rude monitor* to refer to a monitor on which the top\nwindow is a full screen window. RudeWindowFixer is named after this terminology.\n\n(If you are lucky enough to have access to the Windows source, you will find\nthis code in `shell\\twinui\\rudewindowmanager\\lib\\globalrudewindowmanager.cpp`.)\n\nRoughly, the rude window manager is implemented as follows:\n\n1. Listen for specific window management events. Most of these events come from\n   [shell hook messages][], which are generated by the kernel (`win32k`). For\n   the purpose of this discussion, we are mostly interested in:\n     - Windows entering or exiting full screen status. These are codified\n       using undocumented `wParam` values `0x35` and `0x36`, respectively.\n       These appear to be generated based on window dimension changes.\n     - Window activation events (`HSHELL_WINDOWACTIVATED` and\n       `HSHELL_RUDEAPPACTIVATED` messages - note the differences between the two\n       aren't clear, and the rude window manager treats them the same).\n2. If one of these events occur,\n   `twinui!CGlobalRudeWindowManager::RecalculateRudeWindowState()` will look at\n   each monitor and determine if it should be considered \"rude\".\n3. In the event a monitor \"rudeness\" changes, notifications are delivered to\n   other components through `CRudeWindowManager`.\n   - This notably includes the code in charge of the taskbar, through\n     `Explorer!CTray::OnRudeWindowStateChange()`, which calls\n     `Taskbar!TrayUI::RudenessChanged()`, which calls\n     `Taskbar!TrayUI::_ResetZorder()`, which finally sets or unsets the \"always\n     on top\" property of the taskbar window based on the new state.\n\nLet's focus on step (2).\n\n### What makes a monitor \"rude\"?\n\n`RecalculateRudeWindowState()` looks at the properties of visible windows to\nmake this determination. For the purpose of this discussion, the most relevant\nproperty is the window dimensions (i.e. its spatial coordinates and size).\nThese are determined by\n`RudeWindowWin32Functions::GetWindowRectForFullscreenCheck()` which internally\nuses [`GetWindowRect()`][].\n\n(If the window has any of the `WS_THICKFRAME` or `WS_CAPTION` [style\nbits][window style], i.e. it has a border, then [`GetClientRect()`][] is used\ninstead and the result is converted to screen coordinates using\n[`MapWindowPoints()`]. This subtlety doesn't matter much for the purposes of\nthis discussion.)\n\nA window is deemed to be located *on* a monitor if its dimensions overlap with\nthat monitor.\n\nWithin the set of windows that are on a given monitor, the window that comes at\nthe top of the [Z-order][] is defined as the *top* (foreground) window for that\nmonitor.\n\nThe Rude Window Manager internally keeps track of a set of full screen windows.\nA window is added to that set upon receipt of a \"full screen enter\" (`0x35`)\nshell hook message. It is removed from the set upon receipt of a \"full screen\nexit\" (`0x36`) shell hook message.\n\nIf the top window on a given monitor is found in the set of full screen windows,\nthen the monitor is considered *rude*.\n\n### Transparent full screen windows\n\nNow, at this point, if you are not using any full screen applications (games,\nvideo players), you might wonder how this pertains to your case in any way.\n\nHere's how: you might actually be staring at a full screen window right now. You\njust can't *see* it!\n\nIndeed, it is possible for applications to set up windows that are:\n\n- *Transparent*, using the [layered window][] mechanism (`WS_EX_LAYERED`\n  [extended window style][]), combined with transparency effects such as\n  `WS_EX_TRANSPARENT` or [`SetLayeredWindowAttributes()`][].\n- *Click-through*, using the same layered window mechanism. This prevents the\n  window from capturing user input, which instead passes through to the window\n  below it.\n- *Not listed* in window lists such as the taskbar or ALT+TAB, again using\n  specific styles.\n\nIf a full screen window does all of the above, then it *de facto* becomes\nessentially invisible to the user; it's as if the window isn't there. This\nbasically means you can have full screen windows on your monitor without\nrealizing it.\n\nConsider this: these sneaky full screen windows might be invisible to the user,\nbut *they are definitely visible to the Rude Window Manager!* More specifically,\nthe window will still be added to the Rude Window Manager's set of full screen\nwindows.\n\nNow, if that transparent full screen window happens to also be \"always on top\"\n(i.e. it has the `WS_EX_TOPMOST` extended window style), then it's game over\nalready: the Rude Window Manager will always see that window as the top window,\nand since it's in its full screen window set, the monitor will be considered\nrude. As a result, the taskbar loses its always on top status for as long as the\nsituation persists.\n\nYou can spot these transparent full screen windows using specialized tools such\nas [GuiPropView][] or [WindowInvestigator][] WindowMonitor. A notable example\ncomes from the [GeForce Experience][] overlay, which displays such a window when\ndisplaying information on some part of the screen; e.g. a corner notification,\nor performance statistics. [WindowInvestigator][] also provides a\nTransparentFullscreenWindow tool that simulates a transparent full screen\nwindow.\n\n![GeForce experience overlay DT window properties](geforce-experience-overlay-dt.png)\n\nThis is one relatively simple scenario where the taskbar always on top state can\nbe messed up. However, problems can still occur even if the transparent full\nscreen window is *not* always on top, and is not even the current top window.\nClearly, there's at least one other failure mode we're still missing. This is\nwhere things get more complicated.\n\n### Asking for trouble: rudeness state desynchronization\n\nOne fundamental problem with the way `CGlobalRudeWindowManager` works is that\nit looks at a wide set of window properties, *but it is not necessarily notified\nwhen some of these properties change*. Indeed the rude window manager only\nlistens to a fairly narrow set of events (mostly window activation events). This\ncan lead to the monitor rudeness state getting out of sync, as it might not be\nrecomputed in response to changes to window properties.\n\nIf this happens, *the taskbar might wrongly behave as if a full screen window is\non top and drop itself to the background (or vice-versa), even though that is\nnot the case*.\n\nIn theory, the missed event could be a change to any kind of property the rude\nwindow manager could be interested in. RudeWindowFixer focuses on one especially\nproblematic scenario that we're going to discuss next.\n\n### Missed changes to window dimensions\n\nConsider the following sequence of events:\n\n1. A window is activated and thus comes to the top (foreground).\n2. `CGlobalRudeWindowManager` runs and calculate the new rudeness state.\n3. The dimensions of the window that was just activated change.\n\nA change to window dimensions is not an event `CGlobalRudeWindowManager` reacts\nto. (It will be notified if the window is becoming full screen - but as we'll\nsee, that won't help with this particular bug.) This can lead to rudeness state\ngetting out of sync.\n\n### A race condition: activating a minimized window\n\nThe animated screencap shown at the top of this document shows the bug being\ntriggered by [activating][] a minimized Firefox window. As it turns out, there\nis a very specific (and quite subtle!) reason why opening a minimized window\ncan trigger a rudeness state desync.\n\nWhen a minimized window is activated (e.g. by clicking on it in the taskbar, as\nshown in the screencap), the following occurs immediately (among other things):\n\n- The minimized (`WS_ICONIC`) [window style][] is removed.\n- The window is moved to the foreground, i.e. the top of the [Z-order][].\n- `HSHELL_WINDOWACTIVATED`/`HSHELL_RUDEAPPACTIVATED` notifications are delivered\n  to [registered listeners][shell hook messages], including the Rude Window\n  Manager.\n- A [`WM_WINDOWPOSCHANGING`][] message is sent to the window.\n\nNow here's the important part: *the window dimensions are only updated after the\nwindow has processed the `WM_WINDOWPOSCHANGING` message*. This is because the\nwindow can [make changes][] to the suggested dimensions while processing this\nmessage, so the final dimensions are not known until the message has been\ncompletely handled by the application.\n\nThe amount of time it takes for the change in window dimensions to take place\nis therefore up to the application. It is potentially unbounded, varies\ndepending on the application, and is not necessarily deterministic. This\nexplains why the problem is not always reproducible and seems to occur more or\nless often depending on the application. Firefox seems especially prone to this\nproblem, for example. At the other extreme, you'll have a hard time triggering\nit with something like Notepad. For demonstration purposes, DelayedWindowPos\nfrom the [WindowInvestigator][] toolbox can be used to simulate a window with\narbitrary `WM_WINDOWPOSCHANGING` processing delays.\n\nSo how does this relate to the Rude Window Manager? Well, in this context,\n`RecalculateRudeWindowState()` is called on receipt of the\n`HSHELL_WINDOWACTIVATED` or `HSHELL_RUDEAPPACTIVATED` message, which is sent\naround the same time as `WM_WINDOWPOSCHANGING`. This means that the new rudeness\nstate is calculated *at the same time* the new top window is processing the\n`WM_WINDOWPOSCHANGING` message. These two processes will therefore [race][]\nagainst each other. If the window was quick enough to process the\n`WM_WINDOWPOSCHANGING` message in time, the Rude Window Manager will use the\nfinal dimensions and compute the correct state. Conversely, if the window is too\nslow to process the message, *the Rude Window Manager will operate based on\nstale window dimensions, and potentially compute an incorrect state*.\n\nUnfortunately, the Rude Window Manager is not notified again when window\ndimensions finally change (unless it is becoming full screen, but let's assume\nthat's not the case here). Therefore, that incorrect state will persist until\nthe next event occurs - typically, when activating another window.\n\n### Dimensions of minimized windows\n\nWe still need to discuss is why this is a problem for *initially minimized*\nwindows specifically. This is because, for [historical reasons][], Windows moves\nwindows to an arbitrary (-32000, -32000) position when they are minimized. This\nposition is what `RecalculateRudeWindowState()` will see if it \"wins\" the race\nand retrieves the window position before the application had a chance to process\nthe `WM_WINDOWPOSCHANGING` message.\n\nThis is important, because a window that is at coordinates (-32000, -32000)\n*does not overlap with any monitor*. Therefore, the Rude Window Manager will not\nconsider that window to be the top (foreground) window on any monitor. As far as\nthe Rude Window Manager is concerned, it's as if that window does not exist at\nall.\n\nIn contrast, if the window is not initially minimized, then it already has\nproper dimensions, and the Rude Window Manager will correctly determine which\nmonitor it's on, no matter who \"wins\" the race condition. This is why this bug\ntypically only surfaces when activating an *initially minimized* window.\n\n### Full screen windows and minimized windows\n\nAs we just discussed, when the bug is triggered, the Rude Window Manager's\nassessment of which window is the top window is incorrect. Instead of treating\nthe window that was just activated as the top window, the Rude Window Manager\nwill wrongly believe the next window in the Z-order is the top window.\n\nIf that incorrect top window is not a full screen window, then this is not a\nreal problem in practice: the monitor was not rude before, and it's still not\nrude now. The taskbar therefore keeps its \"always on top\" property, and\neverything is still fine.\n\nWe can therefore deduce that this bug only surfaces when activating a minimized\nwindow *and the next window in the Z-order is a full screen window*. In other\nwords, when switching *directly* from a full screen window to an initially\nminimized window.\n\n### Switching from a transparent full screen window\n\nNow, you might object that you're not actually using any full screen\napplications. Even if you are, it's actually pretty hard to switch *directly*\nfrom a full screen window to a minimized window. You could do it from the\ntaskbar, but then you'd need to *activate* the taskbar first, since it's not\nshown on top of full screen applications - but then you're not switching\ndirectly from the full screen window anymore. You could also do it using\nALT+TAB, but that's also indirect since you're going through the ALT+TAB window\nitself. (The ALT+TAB window is a bit special - it is a full screen window, but\nit's not treated as such by the Rude Window Manager, because it has a magic\n`\"NonRudeHWND\"` [window property][] that the Rude Window Manager recognizes.)\n\nHowever, these objections imply *real* full screen applications. Remember the\n*transparent* full screen windows that we mentioned previously? If the top\nwindow happens to be a transparent full screen window, then you might, in fact,\nunknowingly switch directly *from* that window to a minimized window by clicking\nits icon on the taskbar!\n\nBecause transparent full screen windows usually cannot be activated directly by\nthe user, they will naturally tend to fall to the bottom of the window Z-order\n(unless they are \"always on top\" of course, but we've already discussed the case\nof always on top transparent full screen windows). The Rude Window Manager will\ntypically not see them as top (foreground) windows. There is one notable\nexception, though: if all windows are minimized, i.e. the user is looking at the\ndesktop, then a transparent fullscreen window will become the top window, *and\nthe Rude Window Monitor will wrongly conclude the monitor is rude*. At this\npoint *the taskbar has already lost its \"always on top\" state*, but that is not\nyet apparent to the user because there is no opaque window sitting atop the\ntaskbar.\n\nA notable example of a non-always-on-top transparent full screen window that\ncan cause this problem is one of the windows created by the [GeForce\nExperience][] overlay. Yes, GeForce Experience again - but note this is not the\nsame window as the one we previously discussed. This one is not \"always on top\";\nhowever, it *always exists* as long as the overlay feature is enabled, even when\nit's not being used.\n\n![GeForce experience overlay window properties](geforce-experience-overlay.png)\n\nIf the current top window is such a transparent full screen window, and the user\nactivates a minimized window by clicking on its icon in the taskbar, then the\nrace we described previously will take place, the Rude Window Manager can miss\nthe new top window, and fail to switch the monitor to the non-rude state.\n\n### Putting it all together\n\nWe now have all the information we need to reconstruct the sequence of events\nthat trigger the second failure mode we are interested in, in addition to the\nsimpler \"always-on-top transparent full screen window\" failure mode:\n\n1. All windows are minimized and the user is looking at the desktop.\n2. Unbeknownst to the user, they are also looking at a transparent clickthrough\n   full screen window, such as the GeForce experience overlay window.\n3. The last run of `CGlobalRudeWindowManager::RecalculateRudeWindowState()`\n   concluded that the transparent full screen window is on top, and the monitor\n   is therefore rude. The taskbar does not have the \"always on top\" property,\n   but the user is unlikely to notice since they don't have any windows open.\n4. The user activates a minimized window by clicking its taskbar icon.\n5. `CGlobalRudeWindowManager::RecalculateRudeWindowState()` runs. Unfortunately,\n   the activated window dimensions have not been updated yet. The window is\n   still located at the \"dummy\" minimized position (-32000, -32000), which is\n   not on the monitor; therefore, `RecalculateRudeWindowState()` ignores that\n   window, and the computed state ends up the same as (3). The monitor is still\n   rude and the taskbar is not \"always on top\".\n6. The newly activated window finishes processing `WM_WINDOWPOSCHANGING` and\n   the window dimensions are established on the monitor - but at this point it's\n   too late.\n7. Because the Rude Window Manager has already run, and is not triggered by a\n   change in window dimensions, the \"always on top\" property is not reinstated\n   on the taskbar, which ends up falling behind the newly activated window.\n\n![Firefox timeline](firefox-timeline.png)\n\n## How RudeWindowFixer works\n\nRudeWindowFixer listens to the same [shell hook messages][] as the Rude Window\nManager. When an event is received, RudeWindowFixer sets a timer for a fixed\namount of time (currently 50 milliseconds). When the timer elapses,\nRudeWindowFixer does two things:\n\n1. It goes through every [visible][] window, looking for transparent windows.\n   - Currently, a window is considered transparent if it has the `WS_EX_LAYERED`\n     as well as `WS_EX_TRANSPARENT` or `WS_EX_NOACTIVATE` [extended window\n     styles][extended window style].\n   - If a transparent window is found, RudeWindowFixer will ensure it is *not*\n     included in the Rude Windows Manager's set of full screen windows.\n     - It does this by adding a \"magic\" undocumented [window property][]\n       (`\"NonRudeHWND\"`) that the Rude Window Manager is known to look for.\n     - It also sends a \"full screen exit\" message to the Rude Window Manager\n       just in case the window was already in the set.\n2. It forces the Rude Window Manager to recalculate rudeness state again by\n   sending it a dummy message.\n\nThe above approach tackles the problem from two angles at the same time:\nRudeWindowFixer tries to ensure transparent windows are never treated as full\nscreen windows, while attempting to mitigate `WM_WINDOWPOSCHANGING` race\nconditions by \"poking\" the Rude Window Manager again after some amount of time\nhas elapsed.\n\nThe 50 ms timer interval should be more than enough time for the activated\nwindow to finish processing the `WM_WINDOWPOSCHANGING` message. (For example,\nFirefox takes less than ~20 ms.) Therefore, by the time the Rude Window Manager\nis forced to run a second time, the window should have settled unto its final\nposition, and the Rude Window Manager should therefore be able to determine the\ncorrect top window.\n\nObviously the fixed delay is somewhat arbitrary, and it is entirely possible for\na window to take more than 50 milliseconds to settle. A more robust solution\nwould trigger the Rude Window Manager as soon as the `WM_WINDOWPOSCHANGING`\nmessage has been processed, regardless of how long that takes. This might be\ntechnically feasible using [hooks][], but such an approach would be complicated\nand would present higher potential for harmful side effects.\n\nThe delayed operation is also useful when dealing with windows that are *not*\ncreated as transparent, but become transparent shortly afterwards. This is the\ncase for the GeForce Experience \"DT\" window, for example.\n\nIn theory, RudeWindowFixer can mitigate any issue where the Rude Window Manager\nis wrongly treating a transparent window as full screen, and/or races against\na shell hook event, including issues that do not necessarily follow the precise\nsequence of events described above. Therefore, RudeWindowFixer could help even\nif your situation does not exactly match the one RudeWindowFixer was designed to\naddress. However, RudeWindowFixer is unlikely to help with Rude Window Manager\nbugs that do not involve transparent windows (as defined above) nor shell hook\nmessage race conditions.\n\n## Tracing\n\nRudeWindowFixer logs every event through an [Event Tracing for Windows (ETW)][]\nprovider. This can be used to troubleshoot RudeWindowFixer operation.\n\nThe provider GUID is `F7A4605A-5EBA-46A2-8A75-D7E2FECC8D62`. You can enter that\nGUID directly in [TraceView][] for real time logging, or you can load the\nincluded [`RudeWindowFixer.wprp`][] [recording profile][] into the [Windows\nPerformance Recorder (WPR)][] for a more thorough analysis. The Provider Name\nwill appear as `RudeWindowFixer`.\n\n## See also\n\n- This [SuperUser question][superuser1] and [this one][superuser2] discuss\n  taskbar always on top issues.\n- This [bug report][eclipse] is the first known public report of what looks like\n  similar issues, going all the way back to 2002!\n- The [WindowInvestigator][] toolbox provides useful tools if you want to\n  investigate similar issues yourself.\n\n## Developer information\n\n[![.github/workflows/continuous-integration.yml](https://github.com/dechamps/RudeWindowFixer/actions/workflows/continuous-integration.yml/badge.svg)](https://github.com/dechamps/RudeWindowFixer/actions/workflows/continuous-integration.yml)\n\nRudeWindowFixer is designed to be built using CMake within the Microsoft Visual\nC++ 2019 toolchain native CMake support.\n\nThere are no dependencies besides the Windows SDK.\n\n[activating]: https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#active-window\n[bug report]: https://bugs.eclipse.org/bugs/show_bug.cgi?id=24052\n[eclipse]: https://bugs.eclipse.org/bugs/show_bug.cgi?id=24052\n[Etienne Dechamps]: mailto:etienne@edechamps.fr\n[extended window style]: https://docs.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles\n[Event Tracing for Windows (ETW)]: https://docs.microsoft.com/en-us/windows/win32/etw/about-event-tracing\n[file an issue]: https://github.com/dechamps/RudeWindowFixer/issues\n[`GetClientRect()`]: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclientrect\n[`GetWindowRect()`]: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowrect\n[GuiPropView]: https://www.nirsoft.net/utils/gui_prop_view.html\n[historical reasons]: https://devblogs.microsoft.com/oldnewthing/?p=37453\n[GeForce Experience]: https://www.nvidia.com/en-gb/geforce/geforce-experience/\n[GitHub]: https://github.com/dechamps/RudeWindowFixer\n[GitHub releases page]: https://github.com/dechamps/RudeWindowFixer/releases\n[hooks]: https://docs.microsoft.com/en-us/windows/win32/winmsg/hooks\n[issue2]: https://github.com/dechamps/RudeWindowFixer/issues/2\n[issue3]: https://github.com/dechamps/RudeWindowFixer/issues/3\n[issue4]: https://github.com/dechamps/RudeWindowFixer/issues/4\n[make changes]: https://devblogs.microsoft.com/oldnewthing/20080116-00/?p=23803\n[KB5011493]: https://support.microsoft.com/en-gb/topic/march-8-2022-kb5011493-os-build-22000-556-8f77cda3-9d4b-4b85-b6a4-34d5e3c98434\n[`MapWindowPoints()`]: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-mapwindowpoints\n[Microsoft bug report]: https://aka.ms/AAfmyzk\n[layered window]: https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#layered-windows\n[WindowInvestigator]: https://github.com/dechamps/WindowInvestigator\n[public Microsoft symbols]: https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/microsoft-public-symbols\n[race]: https://en.wikipedia.org/wiki/Race_condition\n[recording profile]: https://docs.microsoft.com/en-us/windows-hardware/test/wpt/authoring-recording-profiles\n[reverse engineering]: https://en.wikipedia.org/wiki/Reverse_engineering#Binary_software\n[TraceView]: https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/traceview\n[`RudeWindowFixer.wprp`]: RudeWindowFixer.wprp\n[`SetLayeredWindowAttributes()`]: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setlayeredwindowattributes\n[shell hook messages]: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registershellhookwindow\n[superuser1]: https://superuser.com/questions/1163969/windows-10-taskbar-is-not-always-on-top\n[superuser2]: https://superuser.com/questions/483453/windows-7-task-bar-stuck-in-hiding-how-to-fix\n[visible]: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-iswindowvisible\n[window style]: https://docs.microsoft.com/en-us/windows/win32/winmsg/window-styles\n[window property]: https://docs.microsoft.com/en-us/windows/win32/winmsg/window-properties\n[run on startup]: https://www.howtogeek.com/228467/how-to-make-a-program-run-at-startup-on-any-computer/\n[Z-order]: https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#z-order\n[Windows Performance Recorder (WPR)]: https://docs.microsoft.com/en-us/windows-hardware/test/wpt/windows-performance-recorder\n[`WM_WINDOWPOSCHANGING`]: https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-windowposchanging\n[WindowInvestigator]: https://github.com/dechamps/WindowInvestigator\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdechamps%2Frudewindowfixer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdechamps%2Frudewindowfixer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdechamps%2Frudewindowfixer/lists"}