RamonUnch / AltSnap

Maintained continuation of Stefan Sundin's AltDrag
GNU General Public License v3.0
2.21k stars 74 forks source link

Feature Request: Smart Aero Snap without hotkey #83

Closed ducalex closed 3 years ago

ducalex commented 3 years ago

Would it be possible to have an option to trigger smart aero snap when a window is dragged normally by its title bar? In other words replace Window's own snap.

I absolutely love the smart aero snap feature but I'm always a tad annoyed to have a different snapping behaviour when I drag without hotkey.

RamonUnch commented 3 years ago

It is possible, I did not include the option because I think that it can be al little risky, because it means that if there is a problem with AltDrag and it is in a stuck state, it may happen that you can no longer move windows normally.

Try this version Of hooks.dll and set TitlebarMove=1 in the [Advanced] section of AltDrag.ini hooks.zip

ducalex commented 3 years ago

Try this version Of hooks.dll and set TitlebarMove=1 in the [Advanced] section of AltDrag.ini hooks.zip

Thanks! I've been running it for a couple days and the snapping works beautifully. It occasionally interferes with titlebar operations (clicking min/max/close/icon/right click) in some windows. Not always and not all windows so I'm not sure how reproducible the issue is.

RamonUnch commented 3 years ago

In some cases the cursor may no longer point into in the titlebar and in this case when releasing the click AltDrag will not release the hook correctly. This should be fixed here: hooks.zip Also some programs with fake titlebars sometime improperly tag the close button as part of the titlebar, making it impossible for AltDrag to guess where the mouse is really pointing.

Ichisich commented 3 years ago

I tested this feature with AltSnaptest6.zip, so I don't know if this feature has already a better implementation, but so far the only program which the hook has problems detecting buttons with is the Windows 10 explorer.

Further, there are some UWP apps which completely ignore any attempt on AltSnap dragging on the titlebar e.g. Photos and Movies&TV. Curiously, said apps have one spot AltSnap can hook on the titlebar: drag

RamonUnch commented 3 years ago

This is expected, and unfortunately there is not much that can be done about it. AltDrag relies on the WM_NCHITTEST message, the window should respond 2 if it is in a titlebar. If the program has a special titlebar, then sometime they are not "tagged" properly and AltSnap has no way to diferenciate between a click in the titlebar and a click inside the client area of the window. This is very common problem with metro apps

You can check for yourself in the Identify window section of the Blacklist tab. click in the titlebar, and if WM_NCHITTEST displays 2, then it should work, otherwise it wont .

There is a single remaining solution, that would be to make a list of those special windows and treat them specially by knowing that the top section of the window corresponds to the titlebar and by ignoring the response to the message. It would be a case by case approach whick I do not like to do. I would prefer people to fix their programs. See issue https://github.com/RamonUnch/AltSnap/issues/11 for more details

Ichisich commented 3 years ago

Yea, an individualist approach is less messy in the long run. Hearing that even Microsoft will refocus on win32 with Windows 11, it maybe won't even matter.

But I'm still curious about the Windows 10 Explorer. The buttons turn out standard WM_NCHITTEST values 8/9/20 for minimize/maximize/close.

RamonUnch commented 3 years ago

But I'm still curious about the Windows 10 Explorer. The buttons turn out standard WM_NCHITTEST values 8/9/20 for minimize/maximize/close.

This is expected indeed, have a look at the doc from MS: https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-nchittest

Return code/value | Description -- | -- HTBORDER 18 | In the border of a window that does not have a sizing border. HTBOTTOM 15 | In the lower-horizontal border of a resizable window (the user can click the mouse to resize the window vertically). HTBOTTOMLEFT 16 | In the lower-left corner of a border of a resizable window (the user can click the mouse to resize the window diagonally). HTBOTTOMRIGHT 17 | In the lower-right corner of a border of a resizable window (the user can click the mouse to resize the window diagonally). HTCAPTION 2 | In a title bar. HTCLIENT 1 | In a client area. HTCLOSE 20 | In a Close button. HTERROR -2 | On the screen background or on a dividing line between windows (same as HTNOWHERE, except that the DefWindowProc function produces a system beep to indicate an error). HTGROWBOX 4 | In a size box (same as HTSIZE). HTHELP 21 | In a Help button. HTHSCROLL 6 | In a horizontal scroll bar. HTLEFT 10 | In the left border of a resizable window (the user can click the mouse to resize the window horizontally). HTMENU 5 | In a menu. HTMAXBUTTON 9 | In a Maximize button. HTMINBUTTON 8 | In a Minimize button. HTNOWHERE 0 | On the screen background or on a dividing line between windows. HTREDUCE 8 | In a Minimize button. HTRIGHT 11 | In the right border of a resizable window (the user can click the mouse to resize the window horizontally). HTSIZE 4 | In a size box (same as HTGROWBOX). HTSYSMENU 3 | In a window menu or in a Close button in a child window. HTTOP 12 | In the upper-horizontal border of a window. HTTOPLEFT 13 | In the upper-left corner of a window border. HTTOPRIGHT 14 | In the upper-right corner of a window border. HTTRANSPARENT -1 | In a window currently covered by another window in the same thread (the message will be sent to underlying windows in the same thread until one of them returns a code that is not HTTRANSPARENT). HTVSCROLL 7 | In the vertical scroll bar. HTZOOM 9 | In a Maximize button.
Ichisich commented 3 years ago

Maybe this could help in finding a more general approach.

I have an autohotkey script which lets me minimize and close windows with right mouse and middle mouse on the titlebar. This script has worked with any program I've ever encountered and can reliably separate between buttons and the titlebar:

#If MouseIsOverTitlebar()
RButton::WinMinimize
MButton::WinClose

MouseIsOverTitlebar() {
    static WM_NCHITTEST := 0x84, HTCAPTION := 2
    CoordMode Mouse, Screen
    MouseGetPos x, y, w
    if WinExist("ahk_class Shell_TrayWnd ahk_id " w)  ; Exclude taskbar.
        return false
    SendMessage WM_NCHITTEST,, x | (y << 16),, ahk_id %w%
    WinExist("ahk_id " w)  ; Set Last Found Window for convenience.
    return ErrorLevel = HTCAPTION
}
RamonUnch commented 3 years ago

If I remember well ahk_id corresponds to the ancestor (ROOT) window, this is not what you are supposed to do, you are supposed to look at the window under the pointer and get the parent (edit: not ancestor) window until you get something different from HTTRANSPARENT (-1) However I will try to add an exception to try for HTCAPTION, before the loop you are supposed to do.

Doing the loop was necessary for some programs such as SumatraPDF. Older versions of AltDrag were using the same trick than this ahk script but it was less reliable.

RamonUnch commented 3 years ago

Try this one hooks.zip

I uninstalled all metro AppXs on my windows 10 workstation (because I hate them all), so I cannot test myself.

Ichisich commented 3 years ago

Understandable, they are mostly undercooked. The new hook now works flawlessly with metro/uwp apps but odd Explorer handling still persists.

Not exclusively concerning the new hook, something I didn't notice yesterday, because I minimize via AltSnap or script, was that the minimize button often gets recognized as part of the titlebar (WM_NCHITTEST=2) instead of (WM_NCHITTEST=8). Mostly on standard win32 programs, even when they lack any fancy extra buttons on the titlebar.

Ichisich commented 3 years ago

After some further testing, it seems the red area is falsely considered as titlebar, whereas the green area operates properly: min400

RamonUnch commented 3 years ago

This could be increased by the mod I just made, If there are more problems inform me. But this has never been perfect, especially under Win10.

Probably I will have to revert to the old behavior and the worst that can happen is that the window is not grabbed by AltSnap.

I consider the title bar features to be secondary because the whole point of AltSanp is to move / resize / minimize / maximize / snap windows without the title bar. Personally I no longer ever move windows via their title bar.

Ichisich commented 3 years ago

True, but it has its merits in terms of consistency, although the hassle seems disproportionate. At least I would keep it in the .ini as an experimental feature.

RamonUnch commented 3 years ago

For sure i intend to keep title bar AltSnap grabbing but I will not focus too much effort in making it perfect because it is an "advanced" option when the overall program and code-base will improve, I will spend more time on those details. for now I do implement them if it is easy (which it was).

Next big step is Zone layouts support.

RamonUnch commented 3 years ago

Note for the title bar stuff, You got a backlist that you can set via the .ini only So all windows that are in this list will use the method that you described above: https://github.com/RamonUnch/AltSnap/issues/83#issuecomment-917704145 Of course this alternate method is not the preferred one, so it should be applied only for windows that have troubles. even like this there is no guarantee of course.

NCHittest=*|ApplicationFrameWindow
; List of windows for which AltSnap should try directly to question the
; ancestor window for the Hittest, in order to know were the title bar is.

I would appreciate if you could give me a list of windows in the *|class format that should be in your opinion in the default NCHittest= list, this would be helpful for all users to have a good default. On my side I could only find *|ApplicationFrameWindow that corresponds to the Settings window.

AltSnap1.47test21bin.zip AltSnap1.47test21bin_x64.zip AltSnap1.47test21-installers.zip

xaryangupta commented 3 years ago

You removed alternate key thingy in this one??? image

RamonUnch commented 3 years ago

There must be an error this is an older version, this one should be the one. AltSnap1.47test21x64-inst.zip

xaryangupta commented 3 years ago

image default opacity is 200 now? it was 255 previously i guess?

Ichisich commented 3 years ago

I would appreciate if you could give me a list of windows in the *|class format that should be in your opinion in the default NCHittest= list, this would be helpful for all users to have a good default. On my side I could only find *|ApplicationFrameWindow that corresponds to the Settings window.

On the fly, I would say *|SDL_app should be included. But those are wild with various behaviour quirks. I will try some other applications, but *|ApplicationFrameWindow seems to already cover all nativ Windows UWP/Metroapps.

Ichisich commented 3 years ago

So, I tested all my installed 102 applications and *|ApplicationFrameWindow covers indeed all native Windows applications. There were some obscure programs that didn't work with AltSnap at all and others that don't flag their title bar with 2 but 0 instead. Except from *|SDL_app and *|ApplicationFrameWindow I don't see other application classes which would profit from questioning the ancestor window.

RamonUnch commented 3 years ago

@Ichisich, Perfect, it will be a perfect starting point for the next release.