From 4e29929b15ead3340234ca91ffe01968fc863d64 Mon Sep 17 00:00:00 2001 From: RamonUnch <74856804+RamonUnch@users.noreply.github.com> Date: Thu, 25 Aug 2022 09:56:45 +0100 Subject: [PATCH 1/4] Add files via upload --- altsnap.c | 21 ++- altsnap.nsi | 2 +- altsnap.rc | 6 +- config.c | 3 + hooks.c | 423 +++++++++++++++++++++++++++++++--------------------- hooks.h | 25 +++- hooks.rc | 6 +- languages.h | 12 +- nanolibc.h | 40 +++++ tray.c | 30 ++-- zones.c | 2 - 11 files changed, 370 insertions(+), 200 deletions(-) diff --git a/altsnap.c b/altsnap.c index 1b47b140..410cef54 100644 --- a/altsnap.c +++ b/altsnap.c @@ -174,14 +174,16 @@ void ShowSClickMenu(HWND hwnd, LPARAM param) { 0, MF_SEPARATOR, NULL }, /* ------------------------ */ { AC_KILL, MF_STRING, l10n->input_actions_kill}, { 0, MF_SEPARATOR, NULL }, /* ------------------------ */ + { AC_MOVEONOFF, CHK(LP_MOVEONOFF), l10n->input_actions_moveonoff}, + { 0, MF_SEPARATOR, NULL }, /* ------------------------ */ { AC_NONE, MF_STRING, l10n->input_actions_nothing}, }; #undef CHK #undef K unsigned i; for (i=0; i < ARR_SZ(mnlst); i++) { - if ( (ACMenuItems>>i)&1 ) - AppendMenu(menu, mnlst[i].mf, mnlst[i].action, mnlst[i].str); + if ( (ACMenuItems>>i)&1 ) // Put the action in the HIWORD of wParam + AppendMenu(menu, mnlst[i].mf, mnlst[i].action<<16, mnlst[i].str); } TrackPopupMenu(menu, GetSystemMetrics(SM_MENUDROPALIGNMENT), pt.x, pt.y, 0, hwnd, NULL); DestroyMenu(menu); @@ -383,8 +385,20 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, char *szCmdLine, in // Look for previous instance if (!multi && !GetPrivateProfileInt(L"Advanced", L"MultipleInstances", 0, inipath)){ if (quiet) return 0; - HWND previnst = FindWindow(APP_NAME, NULL); + + HWND previnst = FindWindow(APP_NAME, L""); if (previnst) { + // Ask old HotKey window to perform an action. + const char *actionstr = strstr(params, "-a"); + if (actionstr && actionstr[2] && actionstr[3] && actionstr[4]) { + enum action action = MapActionA(&actionstr[3]); + HWND msghwnd; + if ((msghwnd = FindWindow( APP_NAME"-HotKeys", L""))) { + PostMessage(msghwnd, WM_HOTKEY, (actionstr[2] == 'p')*0x1000+action, 0); + return 0; + } + } + // Update old instance if no action to be made. LOG("Previous instance found and no -multi mode") if(hide) PostMessage(previnst, WM_CLOSECONFIG, 0, 0); if(config) PostMessage(previnst, WM_OPENCONFIG, 0, 0); @@ -458,6 +472,7 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, char *szCmdLine, in } } + UnhookSystem(); DestroyWindow(g_hwnd); LOG("GOOD NORMAL EXIT"); return msg.wParam; diff --git a/altsnap.nsi b/altsnap.nsi index 8004fb10..cd4c247d 100644 --- a/altsnap.nsi +++ b/altsnap.nsi @@ -2,7 +2,7 @@ # define the name of the installer !define APP_NAME "AltSnap" -!define APP_VERSION "1.56" +!define APP_VERSION "1.57" # define the name of the installer OutFile "${APP_NAME}${APP_VERSION}-inst.exe" Name "${APP_NAME} ${APP_VERSION}" diff --git a/altsnap.rc b/altsnap.rc index e1c1067f..197ab449 100644 --- a/altsnap.rc +++ b/altsnap.rc @@ -8,8 +8,8 @@ CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "AltSnap.exe.manifest" #define VS_VERSION_INFO 1 VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,5,6,0 - PRODUCTVERSION 1,5,6,0 + FILEVERSION 1,5,67,0 + PRODUCTVERSION 1,5,7,0 FILEFLAGSMASK 0x3fL FILEFLAGS 0x0L FILEOS 0x40004L @@ -21,7 +21,7 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "AltSnap" - VALUE "FileVersion", "1.56" + VALUE "FileVersion", "1.57" VALUE "InternalName", "altsnap" VALUE "OriginalFilename", "AltSnap.exe" VALUE "CompanyName", "Gillibert Software" diff --git a/config.c b/config.c index 554bd02a..2ee29fd6 100644 --- a/config.c +++ b/config.c @@ -706,6 +706,7 @@ INT_PTR CALLBACK MousePageDialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM {L"NStacked", l10n->input_actions_nstacked}, {L"PStacked", l10n->input_actions_pstacked}, {L"StackList", l10n->input_actions_stacklist}, + {L"StackList2", l10n->input_actions_stacklist2}, {L"Roll", l10n->input_actions_roll}, {L"AlwaysOnTop", l10n->input_actions_alwaysontop}, {L"Borderless", l10n->input_actions_borderless}, @@ -944,6 +945,7 @@ INT_PTR CALLBACK KeyboardPageDialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR {L"Kill", l10n->input_actions_kill}, {L"Pause", l10n->input_actions_pause}, {L"Resume", l10n->input_actions_resume}, + {L"ASOnOff", l10n->input_actions_asonoff}, {L"Lower", l10n->input_actions_lower}, {L"Roll", l10n->input_actions_roll}, {L"AlwaysOnTop", l10n->input_actions_alwaysontop}, @@ -956,6 +958,7 @@ INT_PTR CALLBACK KeyboardPageDialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR {L"PStacked", l10n->input_actions_pstacked}, {L"PStacked2", l10n->input_actions_pstacked2}, {L"StackList", l10n->input_actions_stacklist}, + {L"StackList2", l10n->input_actions_stacklist2}, {L"MLZone", l10n->input_actions_mlzone}, {L"MTZone", l10n->input_actions_mtzone}, {L"MRZone", l10n->input_actions_mrzone}, diff --git a/hooks.c b/hooks.c index a726daec..a4008cf3 100644 --- a/hooks.c +++ b/hooks.c @@ -87,6 +87,7 @@ static struct { UCHAR ctrl; UCHAR shift; UCHAR snap; + UCHAR altsnaponoff; UCHAR moving; UCHAR blockmouseup; @@ -1030,7 +1031,7 @@ static void ResizeSnap(int *posx, int *posy, int *wndwidth, int *wndheight, UCHA ///////////////////////////////////////////////////////////////////////////// // Call with SW_MAXIMIZE or SW_RESTORE or below. #define SW_FULLSCREEN 28 -static void MaximizeRestore_atpt(HWND hwnd, UINT sw_cmd) +static void MaximizeRestore_atpt(HWND hwnd, UINT sw_cmd, int origin) { WINDOWPLACEMENT wndpl; wndpl.length =sizeof(WINDOWPLACEMENT); GetWindowPlacement(hwnd, &wndpl); @@ -1042,6 +1043,12 @@ static void MaximizeRestore_atpt(HWND hwnd, UINT sw_cmd) HMONITOR wndmonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); HMONITOR monitor = MonitorFromPoint(state.prevpt, MONITOR_DEFAULTTONEAREST); + if (origin&1) { + // set normal windpw plasement to origin. + wndpl.rcNormalPosition.right = wndpl.rcNormalPosition.left + state.origin.width; + wndpl.rcNormalPosition.bottom = wndpl.rcNormalPosition.top + state.origin.height; + } + GetMonitorInfo(monitor, &mi); // Center window on monitor, if needed @@ -1049,7 +1056,7 @@ static void MaximizeRestore_atpt(HWND hwnd, UINT sw_cmd) CenterRectInRect(&wndpl.rcNormalPosition, &mi.rcWork); } } -// wndpl.flags |= WPF_ASYNCWINDOWPLACEMENT; + if (origin&2) wndpl.flags |= WPF_ASYNCWINDOWPLACEMENT; SetWindowPlacement(hwnd, &wndpl); if (sw_cmd == SW_FULLSCREEN) { MoveWindowAsync(hwnd, mi.rcMonitor.left , mi.rcMonitor.top @@ -1078,13 +1085,16 @@ static void MoveResizeWindowThread(struct windowRR *lw, UINT flag) hwnd = lw->hwnd; if (lw->end && conf.FullWin) Sleep(8); // At the End of movement... - - SetWindowPos(hwnd, NULL, lw->x, lw->y, lw->width, lw->height, flag); - // Send WM_SYNCPAINT in case to wait for the end of movement - // And to avoid windows to "slide through" the whole WM_MOVE queue - if(flag&SWP_ASYNCWINDOWPOS) SendMessage(hwnd, WM_SYNCPAINT, 0, 0); + if (lw->end && !lw->maximize && (IsZoomed(hwnd) || IsWindowSnapped(hwnd))) { + // Use Restore + RestoreWindowTo(hwnd, lw->x, lw->y, lw->width, lw->height); + } else { + SetWindowPos(hwnd, NULL, lw->x, lw->y, lw->width, lw->height, flag); + // Send WM_SYNCPAINT in case to wait for the end of movement + // And to avoid windows to "slide through" the whole WM_MOVE queue + if(flag&SWP_ASYNCWINDOWPOS) SendMessage(hwnd, WM_SYNCPAINT, 0, 0); if (conf.RefreshRate) ASleep(conf.RefreshRate); // Accurate!!! - + } lw->hwnd = NULL; lw->end = 0; } @@ -1096,7 +1106,11 @@ static void MoveResizeWindowThread(struct windowRR *lw, UINT flag) static DWORD WINAPI MoveWindowThread(LPVOID LastWinV) { struct windowRR *lw = (struct windowRR *)LastWinV; - UINT flag = !lw->moveonly? RESIZEFLAG: state.resizable&2 ? MOVETHICKBORDERS: MOVEASYNC; + RECT rc; + int notsamesize = 0; + if(GetWindowRect(lw->hwnd, &rc)) + notsamesize = rc.right-rc.left != lw->width || rc.bottom-rc.top != lw->height; + UINT flag = notsamesize? RESIZEFLAG: state.resizable&2 ? MOVETHICKBORDERS: MOVEASYNC; MoveResizeWindowThread(lw, flag); return 0; @@ -1207,8 +1221,6 @@ static int AeroMoveSnap(POINT pt, int *posx, int *posy, int *wndwidth, int *wndh int Right = pRight - AERO_TH ; int Top = pTop + AERO_TH ; int Bottom= pBottom - AERO_TH ; - LastWin.moveonly = 0; // We are resizing the window. - // Move window if (pt.y < Top && pt.x < Left) { // Top left @@ -1243,7 +1255,7 @@ static int AeroMoveSnap(POINT pt, int *posx, int *posy, int *wndwidth, int *wndh if (!state.shift ^ !(conf.AeroTopMaximizes&1) && (state.Speed < conf.AeroMaxSpeed)) { if (conf.FullWin) { - MaximizeRestore_atpt(state.hwnd, SW_MAXIMIZE); + MaximizeRestore_atpt(state.hwnd, SW_MAXIMIZE, 1); LastWin.hwnd = NULL; state.moving = 2; return 1; @@ -1293,7 +1305,6 @@ static int AeroMoveSnap(POINT pt, int *posx, int *posy, int *wndwidth, int *wndh restore = 0; *wndwidth = state.origin.width; *wndheight = state.origin.height; - LastWin.moveonly = 0; // Restored => resize } } @@ -1314,14 +1325,16 @@ static int AeroMoveSnap(POINT pt, int *posx, int *posy, int *wndwidth, int *wndh // If we go too fast then do not move the window if (state.Speed > conf.AeroMaxSpeed) return 1; if (conf.FullWin) { - if (IsZoomed(state.hwnd)) MaximizeRestore_atpt(state.hwnd, SW_RESTORE); + if (IsZoomed(state.hwnd)) { + // Avoids flickering + RestoreWindowTo(state.hwnd, *posx, *posy, *wndwidth, *wndheight); + } int mmthreadend = !LastWin.hwnd; LastWin.hwnd = state.hwnd; LastWin.x = *posx; LastWin.y = *posy; LastWin.width = *wndwidth; LastWin.height = *wndheight; - LastWin.moveonly = 0; // Snap => resize LastWin.snap = 1; if (mmthreadend) { MoveWindowInThread(&LastWin); @@ -1448,7 +1461,7 @@ static int NumKeysDown() ///////////////////////////////////////////////////////////////////////////// // index 1 => normal restore on any move restore & 1 // restore & 3 => Both 1 & 2 ie: Maximized then rolled. -static void RestoreOldWin(const POINT pt, unsigned was_snapped) +static void RestoreOldWin(const POINT pt, unsigned was_snapped, RECT *ownd) { // Restore old width/height? unsigned restore = 0; @@ -1457,7 +1470,7 @@ static void RestoreOldWin(const POINT pt, unsigned was_snapped) if (((rdata_flag & SNAPPED) && !(state.origin.maximized&&rdata_flag&2))) { // Set origin width and height to the saved values - if(!state.usezones){ + if (!state.usezones) { restore = rdata_flag; state.origin.width = rwidth; state.origin.height = rheight; @@ -1477,7 +1490,7 @@ static void RestoreOldWin(const POINT pt, unsigned was_snapped) / max(wnd.bottom-wnd.top,1); if (rdata_flag&ROLLED) { - if (state.origin.maximized || was_snapped){ + if (state.origin.maximized || was_snapped) { // if we restore a Rolled Maximized/snapped window... state.offset.y = GetSystemMetrics(SM_CYMIN)/2; } else { @@ -1487,11 +1500,15 @@ static void RestoreOldWin(const POINT pt, unsigned was_snapped) } if (restore) { - SetWindowPos(state.hwnd, NULL - , pt.x - state.offset.x - state.mdipt.x - , pt.y - state.offset.y - state.mdipt.y - , state.origin.width, state.origin.height - , SWP_NOZORDER); +// SetWindowPos(state.hwnd, NULL +// , pt.x - state.offset.x - state.mdipt.x +// , pt.y - state.offset.y - state.mdipt.y +// , state.origin.width, state.origin.height +// , SWP_NOZORDER); + ownd->left = pt.x - state.offset.x - state.mdipt.x; + ownd->top = pt.y - state.offset.y - state.mdipt.y; + ownd->right = ownd->left + state.origin.width; + ownd->bottom = ownd->top + state.origin.height; ClearRestoreData(state.hwnd); } } @@ -1547,14 +1564,14 @@ static BOOL GetMDInfo(POINT *mdicpt, RECT *wnd) } /////////////////////////////////////////////////////////////////////////// // -static void SetOriginFromRestoreData(HWND hnwd, enum action action) +static void SetOriginFromRestoreData(HWND hwnd, enum action action) { // Set Origin width and height needed for AC_MOVE/RESIZE/CENTER/MAXHV int rwidth=0, rheight=0; - unsigned rdata_flag = GetRestoreData(state.hwnd, &rwidth, &rheight); + unsigned rdata_flag = GetRestoreData(hwnd, &rwidth, &rheight); // Clear snapping info if asked. if (rdata_flag&SNCLEAR || (conf.SmartAero&4 && action == AC_MOVE)) { - ClearRestoreData(state.hwnd); + ClearRestoreData(hwnd); rdata_flag=0; } // Replace origin width/height if available in the restore Data. @@ -1672,19 +1689,20 @@ static void MouseMove(POINT pt) if (state.moving == CURSOR_ONLY) return; // Movement was blocked... + static RECT wnd; // wnd will be updated and is initialized once. + if (!state.moving && !GetWindowRect(state.hwnd, &wnd)) return; + int posx=0, posy=0, wndwidth=0, wndheight=0; + // Restore Aero snapped window when movement starts UCHAR was_snapped = 0; if (!state.moving) { SetOriginFromRestoreData(state.hwnd, state.action); if (state.action == AC_MOVE) { was_snapped = IsWindowSnapped(state.hwnd); - RestoreOldWin(pt, was_snapped); + RestoreOldWin(pt, was_snapped, &wnd); } } - static RECT wnd; // wnd will be updated and is initialized once. - if (!state.moving && !GetWindowRect(state.hwnd, &wnd)) return; - int posx=0, posy=0, wndwidth=0, wndheight=0; // Convert pt in MDI coordinates. // state.mdipt is global! @@ -1695,10 +1713,8 @@ static void MouseMove(POINT pt) // Get new position for window LastWin.end = 0; - LastWin.moveonly = 0; if (state.action == AC_MOVE) { // SWP_NOSIZE to SetWindowPos - LastWin.moveonly = 1; posx = pt.x-state.offset.x; posy = pt.y-state.offset.y; @@ -1712,8 +1728,7 @@ static void MouseMove(POINT pt) MoveSnapToZone(pt, &posx, &posy, &wndwidth, &wndheight); // Restore window if maximized when starting - if (was_snapped || IsZoomed(state.hwnd)) { - LastWin.moveonly = 0; + if ((was_snapped || IsZoomed(state.hwnd)) && !LastWin.snap) { WINDOWPLACEMENT wndpl; wndpl.length =sizeof(WINDOWPLACEMENT); GetWindowPlacement(state.hwnd, &wndpl); // Restore original width and height in case we are restoring @@ -1721,6 +1736,8 @@ static void MouseMove(POINT pt) wndpl.showCmd = SW_RESTORE; unsigned restore = GetRestoreFlag(state.hwnd); if (!(restore&ROLLED)) { // Not if window is rolled! + wndpl.rcNormalPosition.left = posx; + wndpl.rcNormalPosition.top = posy; wndpl.rcNormalPosition.right = wndpl.rcNormalPosition.left + state.origin.width; wndpl.rcNormalPosition.bottom= wndpl.rcNormalPosition.top + state.origin.height; } @@ -1728,8 +1745,12 @@ static void MouseMove(POINT pt) // Update wndwidth and wndheight wndwidth = wndpl.rcNormalPosition.right - wndpl.rcNormalPosition.left; wndheight = wndpl.rcNormalPosition.bottom - wndpl.rcNormalPosition.top; -// wndpl.flags |= WPF_ASYNCWINDOWPLACEMENT; - SetWindowPlacement(state.hwnd, &wndpl); + if (!conf.FullWin) { + wndpl.flags |= WPF_ASYNCWINDOWPLACEMENT; + SetWindowPlacement(state.hwnd, &wndpl); + } else { + LastWin.end=1; + } } } else if (state.action == AC_RESIZE) { @@ -1748,7 +1769,7 @@ static void MouseMove(POINT pt) posx = wnd.left - (pt.x - state.offset.x) - state.mdipt.x; posy = wnd.top - (pt.y - state.offset.y) - state.mdipt.y; - // Keep the window it perfectly centered. + // Keep the window perfectly centered. // even when going out of min or max sizes int W = CLAMPW(wndwidth); int dW = wndwidth - W; @@ -2057,8 +2078,10 @@ static void SetForegroundWindowL(HWND hwnd) // otherwise it is enabled by Scroll lock. static int ScrollLockState() { - return (conf.ScrollLockState&1) && - !( !(GetKeyState(VK_SCROLL)&1) ^ !(conf.ScrollLockState&2) ); + return state.altsnaponoff// AltSnap was disabled by AC_ASONOFF + || ( (conf.ScrollLockState&1) + && !( !(GetKeyState(VK_SCROLL)&1) ^ !(conf.ScrollLockState&2) ) + ); } static void LogState(const char *Title) { @@ -2084,7 +2107,6 @@ static void LogState(const char *Title) "lwhwnd=%lx\n" "lwend=%d\n" "lwmaximize=%d\n" - "lwmoveonly=%d\n" "lwsnap=%d\n" "blockaltup=%d\n" "blockmouseup=%d\n" @@ -2094,7 +2116,6 @@ static void LogState(const char *Title) , (DWORD)(DorQWORD)LastWin.hwnd , (int)LastWin.end , (int)LastWin.maximize - , (int)LastWin.moveonly , (int)LastWin.snap , (int)state.blockaltup , (int)state.blockmouseup @@ -2436,7 +2457,7 @@ static pure BOOL StackedRectsT(const RECT *a, const RECT *b, const int T) return RectInRectT(a, b, T) || RectInRectT(b, a, T); } // Similar to the EnumAltTabWindows, to be used in AltTab(); -BOOL CALLBACK EnumStackedWindowsProc(HWND hwnd, LPARAM lParam) +BOOL CALLBACK EnumStackedWindowsProc(HWND hwnd, LPARAM lasermode) { // Make sure we have enough space allocated hwnds = GetEnoughSpace(hwnds, numhwnds, &hwnds_alloc, sizeof(HWND)); @@ -2447,7 +2468,7 @@ BOOL CALLBACK EnumStackedWindowsProc(HWND hwnd, LPARAM lParam) if (IsAltTabAble(hwnd) && GetWindowRectL(state.hwnd, &refwnd) && GetWindowRectL(hwnd, &wnd) - && (state.shift || StackedRectsT(&refwnd, &wnd, conf.SnapThreshold/2) ) + && (lasermode || StackedRectsT(&refwnd, &wnd, conf.SnapThreshold/2) ) && InflateRect(&wnd, conf.SnapThreshold, conf.SnapThreshold) && PtInRect(&wnd, state.prevpt) ){ @@ -2985,12 +3006,13 @@ static void SnapToCorner(HWND hwnd) posx -= bd.left; posy -= bd.top; wndwidth += bd.left+bd.right; wndheight += bd.top+bd.bottom; } - if (IsZoomed(state.hwnd)) - RestoreWindowTo(state.hwnd, posx, posy, wndwidth, wndheight); + if (IsZoomed(hwnd)) + RestoreWindowTo(hwnd, posx, posy, wndwidth, wndheight); else MoveWindowAsync(hwnd, posx, posy, wndwidth, wndheight); // Save data to the window... - SetRestoreData(hwnd, state.origin.width, state.origin.height, SNAPPED|restore); + if ( !(GetRestoreFlag(hwnd)&SNAPPED) ) + SetRestoreData(hwnd, state.origin.width, state.origin.height, SNAPPED|restore); } ///////////////////////////////////////////////////////////////////////////// static int ActionResize(POINT pt, const RECT *wnd, int button) @@ -3103,6 +3125,10 @@ struct pinwindata { //static void TrackMenuOfWindows(HWND menuhwnd, WNDENUMPROC EnumProc); static DWORD WINAPI TrackMenuOfWindows(LPVOID ppEnumProc); +struct TrackMenuOfWindowsparam { + WNDENUMPROC EnumProc; + LPARAM lp; +}; static LRESULT CALLBACK PinWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { switch(msg) { @@ -3207,7 +3233,8 @@ static LRESULT CALLBACK PinWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) } break; case WM_RBUTTONDOWN: { state.mdiclient = NULL; // In case... - TrackMenuOfWindows((LPVOID)EnumTopMostWindows); + struct TrackMenuOfWindowsparam param = { EnumTopMostWindows, 0 }; + TrackMenuOfWindows((LPVOID)¶m); return 0; } break; // case WM_GETPINNEDHWND: { @@ -3283,7 +3310,7 @@ static void MaximizeHV(HWND hwnd, int horizontal) POINT pt; GetCursorPos(&pt); GetMonitorRect(&pt, 0, &mon); - SetOriginFromRestoreData(state.hwnd, AC_MOVE); + SetOriginFromRestoreData(hwnd, AC_MOVE); SetRestoreData(hwnd, state.origin.width, state.origin.height, SNAPPED); FixDWMRect(hwnd, &bd); @@ -3376,7 +3403,7 @@ struct menuitemdata { }; static DWORD WINAPI TrackMenuOfWindows(LPVOID ppEnumProc) { - WNDENUMPROC EnumProc = (WNDENUMPROC)ppEnumProc; + struct TrackMenuOfWindowsparam *param = (struct TrackMenuOfWindowsparam *)ppEnumProc; state.sclickhwnd = NULL; KillAltSnapMenu(); g_mchwnd = KreateMsgWin(MenuWindowProc, APP_NAME"-SClick"); @@ -3385,9 +3412,9 @@ static DWORD WINAPI TrackMenuOfWindows(LPVOID ppEnumProc) numhwnds = 0; HWND mdiclient = state.mdiclient; if (mdiclient) { - EnumChildWindows(mdiclient, EnumProc, 0); + EnumChildWindows(mdiclient, param->EnumProc, param->lp); } else { - EnumDesktopWindows(NULL, EnumProc, 0); + EnumDesktopWindows(NULL, param->EnumProc, param->lp); } state.sclickhwnd = state.hwnd; @@ -3438,10 +3465,26 @@ static DWORD WINAPI TrackMenuOfWindows(LPVOID ppEnumProc) return 0; } -static void ActionStackList() +static void ActionStackList(LPARAM lasermode) { DWORD lpThreadId; - CloseHandle(CreateThread(NULL, STACK, TrackMenuOfWindows, (LPVOID)EnumStackedWindowsProc, 0, &lpThreadId)); + struct TrackMenuOfWindowsparam param; + param.EnumProc = EnumStackedWindowsProc; + param.lp = lasermode; + CloseHandle(CreateThread(NULL, STACK, TrackMenuOfWindows, (LPVOID)¶m, 0, &lpThreadId)); +} +static void ActionASOnOff() +{ + state.altsnaponoff = !GetPropA(g_mainhwnd, APP_ASONOFF); + SetPropA(g_mainhwnd, APP_ASONOFF, (HANDLE)(DorQWORD)state.altsnaponoff); + PostMessage(g_mainhwnd, WM_UPDATETRAY, 0, 0); +} +static void ActionMoveOnOff(HWND hwnd) +{ + if (GetPropA(hwnd, APP_MOVEONOFF)) + RemovePropA(hwnd, APP_MOVEONOFF); + else + SetPropA(hwnd, APP_MOVEONOFF, (HANDLE)1); } static void ActionMenu(HWND hwnd) { @@ -3458,6 +3501,7 @@ static void ActionMenu(HWND hwnd) | !!GetBorderlessFlag(hwnd) << 2 // LP_BORDERLESS | IsZoomed(hwnd) << 3 // LP_MAXIMIZED | !!(GetRestoreFlag(hwnd)&2) << 4 // LP_ROLLED + | !!GetPropA(state.hwnd, APP_MOVEONOFF) << 5 // LP_MOVEONOFF ); } ///////////////////////////////////////////////////////////////////////////// @@ -3484,7 +3528,8 @@ static void SClickActions(HWND hwnd, enum action action) else if (action==AC_NSTACKED2) {state.shift = 1; ActionAltTab(state.prevpt, +1, EnumStackedWindowsProc); state.shift = 0;} else if (action==AC_PSTACKED) ActionAltTab(state.prevpt, -1, EnumStackedWindowsProc); else if (action==AC_PSTACKED2) { state.shift = 1; ActionAltTab(state.prevpt, -1, EnumStackedWindowsProc); state.shift = 0;} - else if (action==AC_STACKLIST) ActionStackList(); + else if (action==AC_STACKLIST) ActionStackList(state.shift); + else if (action==AC_STACKLIST2) ActionStackList(!state.shift); else if (action==AC_MLZONE) MoveWindowToTouchingZone(hwnd, 0, 0); // mLeft else if (action==AC_MTZONE) MoveWindowToTouchingZone(hwnd, 1, 0); // mTop else if (action==AC_MRZONE) MoveWindowToTouchingZone(hwnd, 2, 0); // mBottom @@ -3493,6 +3538,8 @@ static void SClickActions(HWND hwnd, enum action action) else if (action==AC_XTZONE) MoveWindowToTouchingZone(hwnd, 1, 1); // xTop else if (action==AC_XRZONE) MoveWindowToTouchingZone(hwnd, 2, 1); // xBottom else if (action==AC_XBZONE) MoveWindowToTouchingZone(hwnd, 3, 1); // xBight + else if (action==AC_ASONOFF) ActionASOnOff(); + else if (action==AC_MOVEONOFF) ActionMoveOnOff(hwnd); } ///////////////////////////////////////////////////////////////////////////// // @@ -3613,6 +3660,10 @@ static int init_movement_and_actions(POINT pt, HWND hwnd, enum action action, in // Do things depending on what button was pressed if (MOUVEMENT(action)) { + if (GetPropA(state.hwnd, APP_MOVEONOFF)) { + state.action = AC_NONE; + return 0; // Movement was disabled for this window. + } DorQWORD lpdwResult; if(!SendMessageTimeout(state.hwnd, 0, 0, 0, SMTO_NORMAL, 128, &lpdwResult)) { state.blockmouseup = 1; @@ -3740,7 +3791,7 @@ static void FinishMovement() } if (IsWindow(LastWin.hwnd) && !LastWin.snap){ if (LastWin.maximize) { - MaximizeRestore_atpt(LastWin.hwnd, SW_MAXIMIZE); + MaximizeRestore_atpt(LastWin.hwnd, SW_MAXIMIZE, 3); LastWin.hwnd = NULL; } else { LastWin.end = 1; @@ -3765,10 +3816,10 @@ static void FinishMovement() WaitMovementEnd(); // extra waiting in case... if (state.origin.maximized) { - MaximizeRestore_atpt(state.hwnd, SW_MAXIMIZE); + MaximizeRestore_atpt(state.hwnd, SW_MAXIMIZE, 2); } if (state.origin.fullscreen) { - MaximizeRestore_atpt(state.hwnd, SW_FULLSCREEN); + MaximizeRestore_atpt(state.hwnd, SW_FULLSCREEN, 2); } } } @@ -3813,7 +3864,7 @@ static void ClickComboActions(enum action action) state.action = AC_NONE; state.moving = 0; } - MaximizeRestore_atpt(state.hwnd, SW_MAXIMIZE); + MaximizeRestore_atpt(state.hwnd, SW_MAXIMIZE, 2); } state.blockmouseup = 1; } else if (state.action == AC_RESIZE && action == AC_MOVE && !state.moving) { @@ -4132,7 +4183,113 @@ LRESULT CALLBACK TimerWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPar } return DefWindowProc(hwnd, msg, wParam, lParam); } +/////////////////////////////////////////////////////////////////////////// +// Function to calculate the necessary dimentions for the menuitem. +// In response to the WM_MEASUREITEM message +static LPARAM MeasureMenuItem(HWND hwnd, WPARAM wParam, LPARAM lParam) +{ + LPMEASUREITEMSTRUCT lpmi = (LPMEASUREITEMSTRUCT)lParam; + if(!lpmi) return FALSE; + struct menuitemdata *data = (struct menuitemdata *)lpmi->itemData; + if(!data) return FALSE; + wchar_t *text = data->txt; + //LOGA("WM_MEASUREITEM: id=%u, txt=%S", lpmi->itemID, data->txt); + + HDC dc = GetDC(hwnd); + UINT dpi = GetDpiForWindow(hwnd); + + // Select proper font. + HFONT mfont = GetNCMenuFont(dpi); + HFONT oldfont=SelectObject(dc, mfont); + + int xmargin = GetSystemMetricsForDpi(SM_CXFIXEDFRAME, dpi); + int ymargin = GetSystemMetricsForDpi(SM_CYFIXEDFRAME, dpi); + int xicosz = GetSystemMetricsForDpi(SM_CXSMICON, dpi); + int yicosz = GetSystemMetricsForDpi(SM_CYSMICON, dpi); + + SIZE sz; // Get text size in both dimentions + GetTextExtentPoint32(dc, text, wcslen(text), &sz); + // Text width + icon width + 4 margins + lpmi->itemWidth = sz.cx + xicosz + 4*xmargin; + + // Text height/Icon height + margin + lpmi->itemHeight = max(sz.cy, yicosz) + ymargin; + + SelectObject(dc, oldfont); // restore old font + DeleteObject(mfont); // Delete menufont. + ReleaseDC(hwnd, dc); + return TRUE; +} +/////////////////////////////////////////////////////////////////////////// +// Function to custom draw the menu item, in response to WM_DRAWITEM. +// We must both draw he small icon and the menu text. +// We must also draw the selected menu with the highligh color. +static LRESULT DrawMenuItem(HWND hwnd, WPARAM wParam, LPARAM lParam) +{ + LPDRAWITEMSTRUCT di = (LPDRAWITEMSTRUCT)lParam; + if (!di) return FALSE; + struct menuitemdata *data = (struct menuitemdata *)di->itemData; + if (!data) return FALSE; + + // Try to be dpi-aware as good as we can... + UINT dpi = GetDpiForWindow(hwnd); + int xmargin = GetSystemMetricsForDpi(SM_CXFIXEDFRAME, dpi); + int xicosz = GetSystemMetricsForDpi(SM_CXSMICON, dpi); + int yicosz = GetSystemMetricsForDpi(SM_CYSMICON, dpi); + + //LOGA("WM_DRAWITEM: id=%u, txt=%S", di->itemID, data->txt); + + int bgcol, txcol; + if(di->itemState & ODS_SELECTED) { + // Item is highlited + bgcol = COLOR_HIGHLIGHT ; + txcol = COLOR_HIGHLIGHTTEXT ; + } else { + // normal + bgcol = COLOR_MENU ; + txcol = COLOR_MENUTEXT ; + } + HBRUSH bgbrush = GetSysColorBrush(bgcol); + // Set + SetBkColor(di->hDC, GetSysColor(bgcol)); + SetTextColor(di->hDC, GetSysColor(txcol)); + + // Highlight menu entry + HPEN oldpen=SelectObject(di->hDC, GetStockObject(NULL_PEN)); + HBRUSH oldbrush=SelectObject(di->hDC, bgbrush); + Rectangle(di->hDC, di->rcItem.left, di->rcItem.top, di->rcItem.right+1, di->rcItem.bottom+1); + int totheight = di->rcItem.bottom - di->rcItem.top; // total menuitem height + + HFONT mfont = GetNCMenuFont(dpi); + HFONT oldfont=SelectObject(di->hDC, mfont); + + SIZE sz; + GetTextExtentPoint32(di->hDC, data->txt, wcslen(data->txt), &sz); + //LOGA("WM_DRAWITEM: txtXY=%u, %u, txt=%S", (UINT)sz.cx, (UINT)sz.cy, data->txt); + + int yicooffset = (totheight - yicosz)/2; // Center icon vertically + int ytxtoffset = (totheight - sz.cy)/2; // Center text vertically + + DrawIconEx(di->hDC + , di->rcItem.left+xmargin + , di->rcItem.top + yicooffset + , data->icon, xicosz, yicosz + , 0, 0, DI_NORMAL); + // Adjust x offset for Text drawing... + di->rcItem.left += xicosz + xmargin*3; + di->rcItem.top += ytxtoffset; + //LOGA("menuitemheight = %ld", di->rcItem.bottom-di->rcItem.top); + DrawText(di->hDC, data->txt, -1, &di->rcItem, 0); // Menuitem Text + + // Restore dc context + SelectObject(di->hDC, oldfont); // restore old font + DeleteObject(mfont); // Delete menufont. + SelectObject(di->hDC, oldpen); + SelectObject(di->hDC, oldbrush); + + return TRUE; +} ///////////////////////////////////////////////////////////////////////////// // Window for single click commands for menu LRESULT CALLBACK MenuWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) @@ -4147,7 +4304,8 @@ LRESULT CALLBACK MenuWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara // state.sclickhwnd = (HWND)lParam; // Child hwnd that was clicked. } else if (msg == WM_GETCLICKHWND) { return (LRESULT)state.sclickhwnd; - } else if (msg == WM_COMMAND && wParam > 32) { + } else if (msg == WM_COMMAND && LOWORD(wParam)) { + // UNIKEY MENU (LOWORD of wParam munst be non NULL. Send_KEY(VK_BACK); // Errase old char... // Send UCS-2 or Lower+Upper UTF-16 surrogates of the UNICODE char. @@ -4155,9 +4313,9 @@ LRESULT CALLBACK MenuWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara if(HIWORD(wParam)) SendUnicodeKey(HIWORD(wParam)); // Upper surrogate state.sclickhwnd = NULL; - } else if (msg == WM_COMMAND && IsWindow(state.sclickhwnd)) { + } else if (msg == WM_COMMAND && IsWindow(state.sclickhwnd) && HIWORD(wParam) && !LOWORD(wParam)) { // ACTION MENU - enum action action = wParam; + enum action action = HIWORD(wParam); if (action) { state.prevpt = state.clickpt; SClickActions(state.sclickhwnd, action); @@ -4174,103 +4332,10 @@ LRESULT CALLBACK MenuWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara return 0; // OWNER DRAWN MENU !!!!! } else if (msg == WM_MEASUREITEM) { - LPMEASUREITEMSTRUCT lpmi = (LPMEASUREITEMSTRUCT)lParam; - if(!lpmi) return FALSE; - struct menuitemdata *data = (struct menuitemdata *)lpmi->itemData; - if(!data) return FALSE; - wchar_t *text = data->txt; - //LOGA("WM_MEASUREITEM: id=%u, txt=%S", lpmi->itemID, data->txt); - - HDC dc = GetDC(hwnd); - UINT dpi = GetDpiForWindow(hwnd); - - // Select proper font. - HFONT mfont = GetNCMenuFont(dpi); - HFONT oldfont=SelectObject(dc, mfont); - - int xmargin = GetSystemMetricsForDpi(SM_CXFIXEDFRAME, dpi); - int ymargin = GetSystemMetricsForDpi(SM_CYFIXEDFRAME, dpi); - int xicosz = GetSystemMetricsForDpi(SM_CXSMICON, dpi); - int yicosz = GetSystemMetricsForDpi(SM_CYSMICON, dpi); - - SIZE sz; // Get text size in both dimentions - GetTextExtentPoint32(dc, text, wcslen(text), &sz); - - // Text width + icon width + 4 margins - lpmi->itemWidth = sz.cx + xicosz + 4*xmargin; - - // Text height/Icon height + margin - lpmi->itemHeight = max(sz.cy, yicosz) + ymargin; - - SelectObject(dc, oldfont); // restore old font - DeleteObject(mfont); // Delete menufont. - ReleaseDC(hwnd, dc); - return TRUE; - + return MeasureMenuItem(hwnd, wParam, lParam); } else if (msg == WM_DRAWITEM) { // WE MUST DRAW THE MENU ITEM HERE - LPDRAWITEMSTRUCT di = (LPDRAWITEMSTRUCT)lParam; - if (!di) return FALSE; - struct menuitemdata *data = (struct menuitemdata *)di->itemData; - if (!data) return FALSE; - - // Try to be dpi-aware as good as we can... - UINT dpi = GetDpiForWindow(hwnd); - int xmargin = GetSystemMetricsForDpi(SM_CXFIXEDFRAME, dpi); - int xicosz = GetSystemMetricsForDpi(SM_CXSMICON, dpi); - int yicosz = GetSystemMetricsForDpi(SM_CYSMICON, dpi); - -// LOGA("WM_DRAWITEM: id=%u, txt=%S", di->itemID, data->txt); - - int bgcol, txcol; - if(di->itemState & ODS_SELECTED) { - // Item is highlited - bgcol = COLOR_HIGHLIGHT ; - txcol = COLOR_HIGHLIGHTTEXT ; - } else { - // normal - bgcol = COLOR_MENU ; - txcol = COLOR_MENUTEXT ; - } - HBRUSH bgbrush = GetSysColorBrush(bgcol); - // Set - SetBkColor(di->hDC, GetSysColor(bgcol)); - SetTextColor(di->hDC, GetSysColor(txcol)); - - // Highlight menu entry - HPEN oldpen=SelectObject(di->hDC, GetStockObject(NULL_PEN)); - HBRUSH oldbrush=SelectObject(di->hDC, bgbrush); - Rectangle(di->hDC, di->rcItem.left, di->rcItem.top, di->rcItem.right+1, di->rcItem.bottom+1); - int totheight = di->rcItem.bottom - di->rcItem.top; // total menuitem height - - HFONT mfont = GetNCMenuFont(dpi); - HFONT oldfont=SelectObject(di->hDC, mfont); - - SIZE sz; - GetTextExtentPoint32(di->hDC, data->txt, wcslen(data->txt), &sz); -// LOGA("WM_DRAWITEM: txtXY=%u, %u, txt=%S", (UINT)sz.cx, (UINT)sz.cy, data->txt); - - int yicooffset = (totheight - yicosz)/2; // Center icon vertically - int ytxtoffset = (totheight - sz.cy)/2; // Center text vertically - - DrawIconEx(di->hDC - , di->rcItem.left+xmargin - , di->rcItem.top + yicooffset - , data->icon, xicosz, yicosz - , 0, 0, DI_NORMAL); - // Adjust x offset for Text drawing... - di->rcItem.left += xicosz + xmargin*3; - di->rcItem.top += ytxtoffset; -// LOGA("menuitemheight = %ld", di->rcItem.bottom-di->rcItem.top); - DrawText(di->hDC, data->txt, -1, &di->rcItem, 0); // Menuitem Text - - // restore dc context - SelectObject(di->hDC, oldfont); // restore old font - DeleteObject(mfont); // Delete menufont. - SelectObject(di->hDC, oldpen); - SelectObject(di->hDC, oldbrush); - return TRUE; - + return DrawMenuItem(hwnd, wParam, lParam); } else if (msg == WM_MENUCHAR) { // LOGA("WM_MENUCHAR: %X", wParam); // Turn the input character into a menu identifier. @@ -4295,7 +4360,7 @@ LRESULT CALLBACK MenuWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara state.sclickhwnd = NULL; } else if (msg == WM_DESTROY) { if (state.sclickhwnd == fhwndori && IsWindow(fhwndori)) { - // Restore the foreground window + // Restore the old foreground window SetForegroundWindow(fhwndori); } fhwndori = NULL; @@ -4305,23 +4370,43 @@ LRESULT CALLBACK MenuWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara // LOGA("msg=%X, wParam=%X, lParam=%lX", msg, wParam, lParam); return DefWindowProc(hwnd, msg, wParam, lParam); } + LRESULT CALLBACK HotKeysWinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (msg == WM_HOTKEY) { - int action = wParam - 0xC000; // Remove the Offset + int action = 0; + int ptwindow = 0; + if(wParam > 0xC000) { // HOTKEY + // The user Pressed a hotkey. + action = wParam - 0xC000; // Remove the Offset + ptwindow = conf.UsePtWindow; + } else if (0x0000 < wParam && wParam < 0x1000) { + // The user called AltSnap.exe -afACTION + action = wParam - 0x0000; // Remove the Offset + ptwindow = 0; + } else if (0x1000 < wParam && wParam < 0x2000) { + // The user called AltSnap.exe -afACTION + action = wParam - 0x1000; // Remove the Offset + ptwindow = 1; + } + if (action > AC_RESIZE) { // Exclude resize action in case... - // Some actions pass directly through the default blacklists... POINT pt; GetCursorPos(&pt); - if (!conf.UsePtWindow + if (!ptwindow && (action == AC_MENU)) { pt.x = MAXLONG; } - if (action == AC_KILL || action == AC_PAUSE || action == AC_RESUME) { - SClickActions(conf.UsePtWindow? WindowFromPoint(pt): GetForegroundWindow(), action); + static const enum action noinitactions[] = { AC_KILL, AC_PAUSE, AC_RESUME, AC_ASONOFF, 0 }; + if (IsActionInList(action, noinitactions)) { + // Some actions pass directly through the default blacklists... + HWND targethwnd = ptwindow? WindowFromPoint(pt): GetForegroundWindow(); + if (IsWindow(targethwnd)) { + SClickActions(targethwnd, action); + } } else { state.shift = state.ctrl = 0; // In case... - init_movement_and_actions(pt, conf.UsePtWindow? NULL: GetForegroundWindow(), action, 0); + init_movement_and_actions(pt, ptwindow? NULL: GetForegroundWindow(), action, 0); state.blockmouseup = 0; state.hwnd=NULL; } @@ -4472,11 +4557,8 @@ static void readhotkeys(const wchar_t *inipath, const char *name, const wchar_t keys[i] = 0; } // Map action string to actual action enum -static enum action readaction(const wchar_t *inipath, const wchar_t *key) +static enum action MapAction(wchar_t *txt) { - wchar_t txt[32]; - GetPrivateProfileString(L"Input", key, L"Nothing", txt, ARR_SZ(txt), inipath); - static const char *action_map[] = ACTION_MAP; enum action ac; for (ac=0; ac < ARR_SZ(action_map); ac++) { @@ -4484,6 +4566,13 @@ static enum action readaction(const wchar_t *inipath, const wchar_t *key) } return AC_NONE; } +static enum action readaction(const wchar_t *inipath, const wchar_t *key) +{ + wchar_t txt[32]; + GetPrivateProfileString(L"Input", key, L"Nothing", txt, ARR_SZ(txt), inipath); + + return MapAction(txt); +} // Read all buttons actions from inipath static void readbuttonactions(const wchar_t *inipath) { diff --git a/hooks.h b/hooks.h index d7be88a2..2dfda5c4 100644 --- a/hooks.h +++ b/hooks.h @@ -22,16 +22,19 @@ #define LP_BORDERLESS (1<<2) #define LP_MAXIMIZED (1<<3) #define LP_ROLLED (1<<4) +#define LP_MOVEONOFF (1<<5) // App #define APP_NAME L"AltSnap" #define APP_NAMEA "AltSnap" -#define APP_VERSION "1.56" +#define APP_VERSION "1.57" #define APP_PROPPT APP_NAMEA"-RDim" #define APP_PROPFL APP_NAMEA"-RFlag" #define APP_PROPOFFSET APP_NAMEA"-ROffset" #define APP_PRBDLESS APP_NAMEA"-RStyle" #define APP_ROLLED APP_NAMEA"-Rolled" +#define APP_ASONOFF APP_NAMEA"-ASOnOff" +#define APP_MOVEONOFF APP_NAMEA"-MoveOnOff" #define FZ_PROPPT "FancyZones_RestoreSize" #define FZ_PROPZONES "FancyZones_zones" @@ -47,7 +50,6 @@ #define WM_HIDETRAY (WM_USER+10) #define WM_UNIKEYMENU (WM_USER+11) #define WM_GETCLICKHWND (WM_USER+12) -//#define WM_GETPINNEDHWND (WM_USER+13) // List of possible actions enum action { @@ -55,7 +57,7 @@ enum action { , AC_CENTER , AC_ALWAYSONTOP, AC_CLOSE, AC_LOWER, AC_BORDERLESS , AC_KILL, AC_PAUSE, AC_RESUME, AC_MAXHV, AC_MINALL, AC_MUTE , AC_SIDESNAP, AC_NSTACKED, AC_NSTACKED2, AC_PSTACKED, AC_PSTACKED2 - , AC_STACKLIST + , AC_STACKLIST, AC_STACKLIST2, AC_ASONOFF, AC_MOVEONOFF , AC_MLZONE, AC_MTZONE, AC_MRZONE, AC_MBZONE , AC_XLZONE, AC_XTZONE, AC_XRZONE, AC_XBZONE , AC_ROLL, AC_ALTTAB, AC_VOLUME, AC_TRANSPARENCY, AC_HSCROLL @@ -68,7 +70,7 @@ enum action { , "Center", "AlwaysOnTop", "Close", "Lower", "Borderless" \ , "Kill", "Pause", "Resume", "MaximizeHV", "MinAllOther", "Mute" \ , "SideSnap", "NStacked", "NStacked2", "PStacked", "PStacked2" \ - , "StackList" \ + , "StackList", "StackList2", "ASOnOff", "MoveOnOff" \ , "MLZone", "MTZone", "MRZone", "MBZone" \ , "XLZone", "XTZone", "XRZone", "XBZone" \ , "Roll", "AltTab", "Volume", "Transparency", "HScroll" \ @@ -90,6 +92,10 @@ static int pure IsHotkeyy(unsigned char key, const unsigned char *HKlist) } return 0; } +static int pure IsActionInList(const enum action ac, const enum action *aclst) +{ + return IsHotkeyy(ac, aclst); +} // Convert zone number to ini name entry static wchar_t *ZidxToZonestr(int idx, wchar_t *zname) @@ -102,4 +108,15 @@ static wchar_t *ZidxToZonestr(int idx, wchar_t *zname) return zname; } +static enum action MapActionA(const char *txt) +{ + static const char *action_map[] = ACTION_MAP; + enum action ac; + for (ac=0; ac < ARR_SZ(action_map); ac++) { + if(!stricmp(txt, action_map[ac])) return ac; + } + return AC_NONE; + +} #endif /* ALTDRAG_RPC_H */ + diff --git a/hooks.rc b/hooks.rc index 4a98ebb9..fabe066a 100644 --- a/hooks.rc +++ b/hooks.rc @@ -1,6 +1,6 @@ 1 VERSIONINFO - FILEVERSION 1,5,6,0 - PRODUCTVERSION 1,5,6,0 + FILEVERSION 1,5,7,0 + PRODUCTVERSION 1,5,7,0 FILEFLAGSMASK 0x3fL FILEFLAGS 0x0L FILEOS 0x40004L @@ -14,7 +14,7 @@ BEGIN VALUE "FileDescription", "Hooks for AltSnap" VALUE "InternalName", "hooks" VALUE "OriginalFilename", "hooks.dll" - VALUE "FileVersion", "1.56" + VALUE "FileVersion", "1.57" VALUE "CompanyName", "Gillibert Software" VALUE "LegalCopyright", "Gillibert" END diff --git a/languages.h b/languages.h index 73324c9b..4c194ff2 100644 --- a/languages.h +++ b/languages.h @@ -117,6 +117,8 @@ struct strings { wchar_t *input_actions_kill; wchar_t *input_actions_pause; wchar_t *input_actions_resume; + wchar_t *input_actions_asonoff; + wchar_t *input_actions_moveonoff; wchar_t *input_actions_minimize; wchar_t *input_actions_maximize; wchar_t *input_actions_lower; @@ -126,6 +128,7 @@ struct strings { wchar_t *input_actions_pstacked2; wchar_t *input_actions_npstacked; wchar_t *input_actions_stacklist; + wchar_t *input_actions_stacklist2; wchar_t *input_actions_mlzone; wchar_t *input_actions_mtzone; @@ -318,6 +321,8 @@ static const char* l10n_inimapping[] = { "InputActionKill", "InputActionPause", "InputActionResume", + "InputActionASOnOff", + "InputActionMoveOnOff", "InputActionMinimize", "InputActionMaximize", "InputActionLower", @@ -327,6 +332,7 @@ static const char* l10n_inimapping[] = { "InputActionPStacked2", "InputActionNPStacked", "InputActionStackList", + "InputActionStackList2", "InputActionMLZone", "InputActionMTZone", "InputActionMRZone", @@ -508,11 +514,8 @@ static const struct strings en_US = { /* mb5_hc */ L"Mo&use button 5", /* longclickmove */ L"Mo&ve windows with a long left-click", -// /* Aggressive Pause */ L"&Pause process on Alt+Shift+Pause (Alt+Pause to resume)", -// /* Aggressive Kill */ L"&Kill process on Ctrl+Alt+F4\nAlso adds the kill option to the action menu", /* scroll lock state */ L"Suspend/Resume AltSnap based on &Scroll lock state", /* unikeyholdmenu */ L"Pop&up an extended character menu when holding an alphabetic key down", -// /* npsnaped */ L"Select the &next/previous window in the pointed windows stack with Alt+Page up/down", /* keycombo */ L"Use two keys &combo to activate", /* grabwithalt */ L"&Action without click:", /* grabwithaltb */ L"Acti&on without click (alt):", @@ -524,6 +527,8 @@ static const struct strings en_US = { /* kill */ L"&Kill program", /* pause */ L"Pause program", /* resume */ L"Resume program", + /* asonoff */ L"S&uspend/Resume AltSnap", + /* moveonoff */ L"Movement dis&abled", /* minimize */ L"Mi&nimize window", /* maximize */ L"Ma&ximize window", /* lower */ L"&Lower window", @@ -533,6 +538,7 @@ static const struct strings en_US = { /* pstacked 2 */ L"Previous laser stacked window", /* npstacked */ L"Next/Prev stacked window", /* stacklist */ L"Stacked windows list", + /* stacklist */ L"Laser stacked windows list", /* mlzone */ L"Move to the left zone", /* mtzone */ L"Move to the top zone", /* mrzone */ L"Move to the right zone", diff --git a/nanolibc.h b/nanolibc.h index 553d2083..e45cba88 100644 --- a/nanolibc.h +++ b/nanolibc.h @@ -111,6 +111,25 @@ static const char *strchrL(const char *__restrict__ str, const char c) } #define strchr strchrL + +static int atoiL(const char *s) +{ + long int v=0; + int sign=1; + while (*s == ' ') s++; /* || (unsigned int)(*s - 9) < 5u */ + + switch (*s) { + case '-': sign=-1; /* fall through */ + case '+': ++s; + } + while ((unsigned)(*s - '0') < 10u) { + v = v * 10 + (*s - '0'); + ++s; + } + return sign*v; +} +#define atoi atoiL + static int wtoiL(const wchar_t *s) { long int v=0; @@ -251,6 +270,27 @@ static char *strcpyL(char *__restrict__ dest, const char *__restrict__ in) } #define strcpy strcpyL +static int stricmpL(const char* s1, const char* s2) +{ + unsigned x1, x2; + + while (1) { + x2 = *s2 - 'A'; + x2 |= (x2 < 26u) << 5; /* Add 32 if UPPERCASE. */ + + x1 = *s1 - 'A'; + x1 |= (x1 < 26u) << 5; + + s1++; s2++; + if (x2 != x1) + break; + if (x1 == (unsigned)-'A') + break; + } + return x1 - x2; +} +#define stricmp stricmpL + static int wcsicmpL(const wchar_t* s1, const wchar_t* s2) { unsigned x1, x2; diff --git a/tray.c b/tray.c index 89da00fa..a13d0c6f 100644 --- a/tray.c +++ b/tray.c @@ -57,9 +57,12 @@ static int InitTray() static int UpdateTray() { int Index = !!ENABLED(); - if (Index && (ScrollLockState&1)) - Index += !( !(GetKeyState(VK_SCROLL)&1) ^ !(ScrollLockState&2) ); - + if (Index) { + if ((ScrollLockState&1)) + Index = !( !(GetKeyState(VK_SCROLL)&1) ^ !(ScrollLockState&2) ); + else if (GetPropA(g_hwnd, APP_ASONOFF)) + Index=2; + } // Load info tool tip and tray icon strcpy(tray.szTip, traystr[Index]); tray.hIcon = LoadIconA(g_hinst, iconstr[Index]); @@ -172,26 +175,25 @@ static void ShowContextMenu(HWND hwnd) GetCursorPos(&pt); HMENU menu = CreatePopupMenu(); - InsertMenu(menu, -1, MF_BYPOSITION, SWM_TOGGLE, (ENABLED()?l10n->menu_disable:l10n->menu_enable)); - InsertMenu(menu, -1, MF_BYPOSITION, SWM_HIDE, l10n->menu_hide); + AppendMenu(menu, MF_STRING, SWM_TOGGLE, (ENABLED()?l10n->menu_disable:l10n->menu_enable)); + AppendMenu(menu, MF_STRING, SWM_HIDE, l10n->menu_hide); if(VISTA) InsertMenu(menu, -1, elevated?MF_BYPOSITION|MF_GRAYED:MF_BYPOSITION , SWM_ELEVATE, (elevated? l10n->general_elevated: l10n->general_elevate)); - InsertMenu(menu, -1, MF_BYPOSITION|MF_SEPARATOR, 0, NULL); - InsertMenu(menu, -1, MF_BYPOSITION, SWM_CONFIG, l10n->menu_config); - InsertMenu(menu, -1, MF_BYPOSITION, SWM_ABOUT, l10n->menu_about); + AppendMenu(menu, MF_SEPARATOR, 0, NULL); + AppendMenu(menu, MF_STRING, SWM_CONFIG, l10n->menu_config); + AppendMenu(menu, MF_STRING, SWM_ABOUT, l10n->menu_about); if (UseZones&1) { // Zones section - InsertMenu(menu, -1, MF_BYPOSITION|MF_SEPARATOR, 0, NULL); - InsertMenu(menu, -1, MF_BYPOSITION, SWM_TESTWIN, l10n->advanced_testwindow); - InsertMenu(menu, -1, FindWindow(APP_NAME"-test", NULL)? MF_BYPOSITION:MF_BYPOSITION|MF_GRAYED + AppendMenu(menu, MF_SEPARATOR, 0, NULL); + AppendMenu(menu, MF_STRING, SWM_TESTWIN, l10n->advanced_testwindow); + AppendMenu(menu, FindWindow(APP_NAME"-test", NULL)? MF_STRING :MF_STRING|MF_GRAYED , SWM_SAVEZONES, l10n->menu_savezones); } - InsertMenu(menu, -1, MF_BYPOSITION|MF_SEPARATOR, 0, NULL); - - InsertMenu(menu, -1, MF_BYPOSITION, SWM_EXIT, l10n->menu_exit); + AppendMenu(menu, MF_SEPARATOR, 0, NULL); + AppendMenu(menu, MF_STRING, SWM_EXIT, l10n->menu_exit); // Track menu SetForegroundWindow(hwnd); diff --git a/zones.c b/zones.c index d8ac3271..2b50dbf9 100644 --- a/zones.c +++ b/zones.c @@ -116,7 +116,6 @@ static void MoveSnapToZone(POINT pt, int *posx, int *posy, int *width, int *heig if (!ret) return; // Outside of a rect LastWin.end = 0; - LastWin.moveonly = 0; // We are resizing the window. FixDWMRect(state.hwnd, &bd); InflateRectBorder(&rc, &bd); @@ -180,7 +179,6 @@ static void MoveWindowToTouchingZone(HWND hwnd, UCHAR direction, UCHAR extend) CopyRect(&fr, &zrc); } LastWin.end = 0; - LastWin.moveonly = 0; // We are resizing the window. RECT bd; FixDWMRect(hwnd, &bd); InflateRectBorder(&fr, &bd); From 2f7353ae9ef7e60381ab6e692f5ee3c6d2fa83e6 Mon Sep 17 00:00:00 2001 From: RamonUnch <74856804+RamonUnch@users.noreply.github.com> Date: Mon, 29 Aug 2022 14:49:08 +0100 Subject: [PATCH 2/4] Add files via upload --- hooks.c | 90 ++++++++++++++++++++++++++++++++++++++++---------------- unfuck.h | 62 +++++++++++++++++++++++++++++++++----- 2 files changed, 118 insertions(+), 34 deletions(-) diff --git a/hooks.c b/hooks.c index a4008cf3..10e48c5e 100644 --- a/hooks.c +++ b/hooks.c @@ -9,6 +9,7 @@ #include "hooks.h" #define LONG_CLICK_MOVE #define COBJMACROS +static BOOL MoveWindowAsync(HWND hwnd, int posx, int posy, int width, int height); static BOOL CALLBACK EnumMonitorsProc(HMONITOR, HDC, LPRECT , LPARAM ); static LRESULT CALLBACK MenuWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); // Timer messages @@ -382,6 +383,18 @@ static void SendSizeMove(DWORD msg) PostMessage(state.hwnd, msg, 0, 0); } } +/* Helper function to call SetWindowPos with the SWP_ASYNCWINDOWPOS flag */ +static BOOL MoveWindowAsync(HWND hwnd, int posx, int posy, int width, int height) +{ + /* flag = (!flag) * SWP_NOREDRAW; */ +// SendSizeMove(WM_ENTERSIZEMOVE); + BOOL ret = SetWindowPos(hwnd, NULL, posx, posy, width, height + , SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOZORDER|SWP_ASYNCWINDOWPOS); +// Sleep(1); +// SendSizeMove(WM_EXITSIZEMOVE); + return ret; +} + ///////////////////////////////////////////////////////////////////////////// // Overloading of the Hittest function to include a whitelist // x and y are in screen coordinate. @@ -1089,7 +1102,11 @@ static void MoveResizeWindowThread(struct windowRR *lw, UINT flag) // Use Restore RestoreWindowTo(hwnd, lw->x, lw->y, lw->width, lw->height); } else { +// RECT rc = { lw->x, lw->y, lw->x + lw->width, lw->y + lw->height }; +// PostMessage(hwnd, WM_MOUSEMOVE, MK_LBUTTON, MAKELPARAM(state.prevpt.x, state.prevpt.y)); +// if(!(flag&SWP_NOSIZE)) SendMessage(hwnd, WM_SIZING, WMSZ_BOTTOMRIGHT, (LPARAM)&rc); SetWindowPos(hwnd, NULL, lw->x, lw->y, lw->width, lw->height, flag); + // Send WM_SYNCPAINT in case to wait for the end of movement // And to avoid windows to "slide through" the whole WM_MOVE queue if(flag&SWP_ASYNCWINDOWPOS) SendMessage(hwnd, WM_SYNCPAINT, 0, 0); @@ -2053,7 +2070,9 @@ static void ReallySetForegroundWindow(HWND hwnd) // Check existing foreground Window. HWND fore = GetForegroundWindow(); if (fore != hwnd) { - if (state.alt != VK_MENU && state.alt != VK_CONTROL) { + if (state.alt != VK_MENU && state.alt != VK_CONTROL + && !(GetAsyncKeyState(VK_CONTROL)&0x8000) + && !(GetAsyncKeyState(VK_MENU)&0x8000)) { // If the physical Alt or Ctrl keys are not down // We need to activate the window with key input. // CTRL seems to work. Also Alt works but trigers the menu @@ -2460,9 +2479,9 @@ static pure BOOL StackedRectsT(const RECT *a, const RECT *b, const int T) BOOL CALLBACK EnumStackedWindowsProc(HWND hwnd, LPARAM lasermode) { // Make sure we have enough space allocated + hwnds = GetEnoughSpace(hwnds, numhwnds, &hwnds_alloc, sizeof(HWND)); if (!hwnds) return FALSE; // Stop enum, we failed - // Only store window if it's visible, not minimized to taskbar RECT wnd, refwnd; if (IsAltTabAble(hwnd) @@ -3131,10 +3150,17 @@ struct TrackMenuOfWindowsparam { }; static LRESULT CALLBACK PinWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { + static UINT dpi; switch(msg) { case WM_CREATE: { + dpi = GetDpiForWindow(hwnd); // Use pin's hwnd SetTimer(hwnd, 1, conf.PinRate, NULL); } break; + case WM_DPICHANGED: { + dpi = LOWORD(wp); // X and Y dpi should be same. + free((void *)GetWindowLongPtr(hwnd, GWLP_USERDATA)); + SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); + } break; case WM_SETTINGCHANGE: { // Free and resets the windows data. if (wp == SPI_SETNONCLIENTMETRICS) { @@ -3164,19 +3190,20 @@ static LRESULT CALLBACK PinWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) GetWindowRect(ow, &rc); LONG_PTR style = GetWindowLongPtr(ow, GWL_STYLE); struct pinwindata *data; - if ((data = (struct pinwindata *)GetWindowLongPtr(hwnd, GWLP_USERDATA)) && data->OldOwStyle == style) { + if ((data = (struct pinwindata *)GetWindowLongPtr(hwnd, GWLP_USERDATA)) + && data->OldOwStyle == style) { // the data were saved for the correct style!!! SetWindowPos(hwnd, NULL , rc.right-data->rightoffset, rc.top+data->topoffset, 0, 0 , SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE); - return 0; + return 0; // DONE! } + // Calculate offsets, sets window position and save data // to the GWLP_USERDATA stuff! int CapButtonWidth, PinW, PinH; - UINT dpi = GetDpiForWindow(ow); // Use parent window... - PinW = GetSystemMetricsForDpi(SM_CXSIZE, dpi); - PinH = GetSystemMetricsForDpi(SM_CYSIZE, dpi); + PinW = GetSystemMetricsForDpi(SM_CXSIZE, dpi); // Caption button width + PinH = GetSystemMetricsForDpi(SM_CYSIZE, dpi); // Caption button height RECT btrc; if (GetCaptionButtonsRect(ow, &btrc)) { @@ -3184,12 +3211,11 @@ static LRESULT CALLBACK PinWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) } else { UCHAR btnum=0; // Number of caption buttons. if ((style&(WS_SYSMENU|WS_CAPTION)) == (WS_SYSMENU|WS_CAPTION)) { - btnum++; // WS_SYSMENU => Close button [X] - btnum += !!(style&WS_MINIMIZEBOX); // [_] - btnum += !!(style&WS_MAXIMIZEBOX); // [O] - btnum += !!(xstyle&WS_EX_CONTEXTHELP); // [?] + btnum++; // WS_SYSMENU => Close button [X] + btnum += 2 * !!(style&(WS_MINIMIZEBOX|WS_MAXIMIZEBOX)); // [O] [_] + btnum += ( (xstyle&WS_EX_CONTEXTHELP) // [?] + && (style&(WS_MINIMIZEBOX|WS_MAXIMIZEBOX)) != (WS_MINIMIZEBOX|WS_MAXIMIZEBOX) ); } - btnum = min(btnum, 3); // Maximum 3 button. CapButtonWidth = btnum * PinW; } // Adjust PinW and PinH to have nice stuff. @@ -3215,7 +3241,7 @@ static LRESULT CALLBACK PinWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) , SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOOWNERZORDER); return 0; } break; - case WM_PAINT : { + case WM_PAINT: { wchar_t Topchar = HIBYTE(HIWORD(conf.PinColor&0xFF000000)); if (Topchar) { PAINTSTRUCT ps; @@ -3396,9 +3422,10 @@ static wchar_t Int2Accel(int i) return i<26? L'A'+i: L'0'+i-26; } #include +#define MITTLEN 80 struct menuitemdata { MSAAMENUINFO msaa; - wchar_t txt[80]; + wchar_t txt[MITTLEN]; HICON icon; }; static DWORD WINAPI TrackMenuOfWindows(LPVOID ppEnumProc) @@ -3416,6 +3443,8 @@ static DWORD WINAPI TrackMenuOfWindows(LPVOID ppEnumProc) } else { EnumDesktopWindows(NULL, param->EnumProc, param->lp); } + LOG("Number of stacked windows = %u", numhwnds); + if(numhwnds == 0) return 0; state.sclickhwnd = state.hwnd; numhwnds = min(numhwnds, 36); // Max 36 stacked windows @@ -3427,7 +3456,7 @@ static DWORD WINAPI TrackMenuOfWindows(LPVOID ppEnumProc) struct menuitemdata *data = calloc(numhwnds, sizeof(struct menuitemdata)); for (i=0; iitemID, data->txt); HDC dc = GetDC(hwnd); - UINT dpi = GetDpiForWindow(hwnd); // Select proper font. HFONT mfont = GetNCMenuFont(dpi); @@ -4225,7 +4254,7 @@ static LPARAM MeasureMenuItem(HWND hwnd, WPARAM wParam, LPARAM lParam) // Function to custom draw the menu item, in response to WM_DRAWITEM. // We must both draw he small icon and the menu text. // We must also draw the selected menu with the highligh color. -static LRESULT DrawMenuItem(HWND hwnd, WPARAM wParam, LPARAM lParam) +static LRESULT DrawMenuItem(HWND hwnd, WPARAM wParam, LPARAM lParam, UINT dpi) { LPDRAWITEMSTRUCT di = (LPDRAWITEMSTRUCT)lParam; if (!di) return FALSE; @@ -4233,7 +4262,6 @@ static LRESULT DrawMenuItem(HWND hwnd, WPARAM wParam, LPARAM lParam) if (!data) return FALSE; // Try to be dpi-aware as good as we can... - UINT dpi = GetDpiForWindow(hwnd); int xmargin = GetSystemMetricsForDpi(SM_CXFIXEDFRAME, dpi); int xicosz = GetSystemMetricsForDpi(SM_CXSMICON, dpi); int yicosz = GetSystemMetricsForDpi(SM_CYSMICON, dpi); @@ -4294,11 +4322,14 @@ static LRESULT DrawMenuItem(HWND hwnd, WPARAM wParam, LPARAM lParam) // Window for single click commands for menu LRESULT CALLBACK MenuWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + static UINT dpi; static HWND fhwndori = NULL; if (msg == WM_CREATE) { // Save the original foreground window. + dpi = GetDpiForWindow(hwnd); fhwndori = GetForegroundWindow(); - + } else if (msg == WM_DPICHANGED) { + dpi = LOWORD(wParam); // Update dpi value if changed... } else if (msg == WM_INITMENU) { state.unikeymenu = (HMENU)wParam; // state.sclickhwnd = (HWND)lParam; // Child hwnd that was clicked. @@ -4306,6 +4337,7 @@ LRESULT CALLBACK MenuWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara return (LRESULT)state.sclickhwnd; } else if (msg == WM_COMMAND && LOWORD(wParam)) { // UNIKEY MENU (LOWORD of wParam munst be non NULL. + LOG("Unikey menu WM_COMMAND, wp=%X, lp=%X", (UINT)wParam, (UINT)lParam); Send_KEY(VK_BACK); // Errase old char... // Send UCS-2 or Lower+Upper UTF-16 surrogates of the UNICODE char. @@ -4315,6 +4347,7 @@ LRESULT CALLBACK MenuWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara state.sclickhwnd = NULL; } else if (msg == WM_COMMAND && IsWindow(state.sclickhwnd) && HIWORD(wParam) && !LOWORD(wParam)) { // ACTION MENU + LOG("Action Menu WM_COMMAND, wp=%X, lp=%X", (UINT)wParam, (UINT)lParam); enum action action = HIWORD(wParam); if (action) { state.prevpt = state.clickpt; @@ -4332,10 +4365,10 @@ LRESULT CALLBACK MenuWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara return 0; // OWNER DRAWN MENU !!!!! } else if (msg == WM_MEASUREITEM) { - return MeasureMenuItem(hwnd, wParam, lParam); + return MeasureMenuItem(hwnd, wParam, lParam, dpi); } else if (msg == WM_DRAWITEM) { // WE MUST DRAW THE MENU ITEM HERE - return DrawMenuItem(hwnd, wParam, lParam); + return DrawMenuItem(hwnd, wParam, lParam, dpi); } else if (msg == WM_MENUCHAR) { // LOGA("WM_MENUCHAR: %X", wParam); // Turn the input character into a menu identifier. @@ -4359,6 +4392,7 @@ LRESULT CALLBACK MenuWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara // Menu gets hiden, be sure to zero-out the clickhwnd state.sclickhwnd = NULL; } else if (msg == WM_DESTROY) { + LOG("Destroying Menu window!"); if (state.sclickhwnd == fhwndori && IsWindow(fhwndori)) { // Restore the old foreground window SetForegroundWindow(fhwndori); @@ -4380,6 +4414,7 @@ LRESULT CALLBACK HotKeysWinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara // The user Pressed a hotkey. action = wParam - 0xC000; // Remove the Offset ptwindow = conf.UsePtWindow; + LOG("Hotkey Pressed, action = %d", action); } else if (0x0000 < wParam && wParam < 0x1000) { // The user called AltSnap.exe -afACTION action = wParam - 0x0000; // Remove the Offset @@ -4407,8 +4442,7 @@ LRESULT CALLBACK HotKeysWinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara } else { state.shift = state.ctrl = 0; // In case... init_movement_and_actions(pt, ptwindow? NULL: GetForegroundWindow(), action, 0); - state.blockmouseup = 0; - state.hwnd=NULL; + state.blockmouseup = 0; // We must not block mouseup in this case... } return 0; } @@ -4840,7 +4874,11 @@ __declspec(dllexport) void Load(HWND mainhwnd) if(LOBYTE(HK) && HIBYTE(HK)) { // Lobyte is the virtual key code and hibyte is the mod_key if(!RegisterHotKey(g_hkhwnd, 0xC000 + ac, HIBYTE(HK), LOBYTE(HK))) { - LOG("Error registering hotkey %s=%x", action_names[ac], (unsigned)HK); + // LOG("Error registering hotkey %s=%x", action_names[ac], (unsigned)HK); + wchar_t title[256]; + wcscpy(title, APP_NAME": unable to register hotkey for action "); + wcscat(title, txt); + ErrorBox(title); } } } diff --git a/unfuck.h b/unfuck.h index 039ae110..fb4a32cc 100644 --- a/unfuck.h +++ b/unfuck.h @@ -32,6 +32,12 @@ enum DWMWINDOWATTRIBUTE { DWMWA_PASSIVE_UPDATE_MODE, DWMWA_LAST }; +enum MONITOR_DPI_TYPE { + MDT_EFFECTIVE_DPI = 0, + MDT_ANGULAR_DPI = 1, + MDT_RAW_DPI = 2, + MDT_DEFAULT = MDT_EFFECTIVE_DPI +}; /* Invalid pointer with which we initialize * all dynamically imported functions */ @@ -65,6 +71,10 @@ enum DWMWINDOWATTRIBUTE { #define NIIF_USER 0x00000004 #endif +#ifndef WM_DPICHANGED +#define WM_DPICHANGED 0x02E0 +#endif + #ifndef SUBCLASSPROC typedef LRESULT (CALLBACK *SUBCLASSPROC) (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam @@ -115,10 +125,32 @@ static BOOL (WINAPI *mySystemParametersInfoForDpi)(UINT uiAction, UINT uiParam, static HRESULT (WINAPI *myDwmGetWindowAttribute)(HWND hwnd, DWORD a, PVOID b, DWORD c) = IPTR; static HRESULT (WINAPI *myDwmIsCompositionEnabled)(BOOL *pfEnabled) = IPTR; +/* SHCORE.DLL */ +static HRESULT (WINAPI *myGetDpiForMonitor)(HMONITOR hmonitor, int dpiType, UINT *dpiX, UINT *dpiY) = IPTR; + /* NTDLL.DLL */ static LONG (NTAPI *myNtSuspendProcess)(HANDLE ProcessHandle) = IPTR; static LONG (NTAPI *myNtResumeProcess )(HANDLE ProcessHandle) = IPTR; +/* Helper function to pop a message bow with error code*/ +static void ErrorBox(TCHAR *title) +{ + LPVOID lpMsgBuf; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ + (LPTSTR) &lpMsgBuf, + 0, NULL + ); + MessageBox( NULL, (LPCTSTR)lpMsgBuf, title, MB_OK | MB_ICONWARNING ); + /* Free the buffer using LocalFree. */ + LocalFree( lpMsgBuf ); +} + /* Removes the trailing file name from a path */ static BOOL PathRemoveFileSpecL(LPTSTR p) { @@ -348,6 +380,18 @@ static int GetSystemMetricsForDpiL(int nIndex, UINT dpi) } #define GetSystemMetricsForDpi GetSystemMetricsForDpiL +static LRESULT GetDpiForMonitorL(HMONITOR hmonitor, int dpiType, UINT *dpiX, UINT *dpiY) +{ + if (myGetDpiForMonitor == IPTR) { /* First time */ + myGetDpiForMonitor=LoadDLLProc("SHCORE.DLL", "GetDpiForMonitor"); + } + if (myGetDpiForMonitor) { /* We know we have the function */ + return myGetDpiForMonitor(hmonitor, dpiType, dpiX, dpiY); + } + return 666; // Fail with 666 error +} + +/* Supported wince Windows 10, version 1607 [desktop apps only] */ static UINT GetDpiForWindowL(HWND hwnd) { if (myGetDpiForWindow == IPTR) { /* First time */ @@ -356,7 +400,16 @@ static UINT GetDpiForWindowL(HWND hwnd) if (myGetDpiForWindow) { /* We know we have the function */ return myGetDpiForWindow(hwnd); } - return 0; /* Not handeled */ + + /* Windows 8.1 / Server2012 R2 Fallback */ + UINT dpiX=0, dpiY=0; + HMONITOR hmon; + if ((hmon = MonitorFromWindowL(hwnd, MONITOR_DEFAULTTONEAREST)) + && S_OK == GetDpiForMonitorL(hmon, MDT_DEFAULT, &dpiX, &dpiY)) { + return dpiX; + } + + return 0; /* Not handled */ } #define GetDpiForWindow GetDpiForWindowL @@ -705,13 +758,6 @@ static HFONT GetNCMenuFont(UINT dpi) return CreateFontIndirect(&ncm.lfMenuFont); } -/* Helper function to call SetWindowPos with the SWP_ASYNCWINDOWPOS flag */ -static BOOL MoveWindowAsync(HWND hwnd, int posx, int posy, int width, int height) -{ - /* flag = (!flag) * SWP_NOREDRAW; */ - return SetWindowPos(hwnd, NULL, posx, posy, width, height - , SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOZORDER|SWP_ASYNCWINDOWPOS); -} static void MaximizeWindow(HWND hwnd) { PostMessage(hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0); From 263f3bac03f0197c97d14e43def7ce73f5336310 Mon Sep 17 00:00:00 2001 From: RamonUnch <74856804+RamonUnch@users.noreply.github.com> Date: Tue, 30 Aug 2022 11:23:24 +0100 Subject: [PATCH 3/4] Avois stupid carsh abd prevent ESC == A --- hooks.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/hooks.c b/hooks.c index 10e48c5e..b4b8f8c4 100644 --- a/hooks.c +++ b/hooks.c @@ -2493,6 +2493,7 @@ BOOL CALLBACK EnumStackedWindowsProc(HWND hwnd, LPARAM lasermode) ){ hwnds[numhwnds++] = hwnd; } + LOG("EnumStackedWindowsProc"); return TRUE; } //////////////////////////////////////////////////////////////////////////// @@ -3259,7 +3260,7 @@ static LRESULT CALLBACK PinWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) } break; case WM_RBUTTONDOWN: { state.mdiclient = NULL; // In case... - struct TrackMenuOfWindowsparam param = { EnumTopMostWindows, 0 }; + static const struct TrackMenuOfWindowsparam param = { EnumTopMostWindows, 0 }; TrackMenuOfWindows((LPVOID)¶m); return 0; } break; @@ -3434,7 +3435,7 @@ static DWORD WINAPI TrackMenuOfWindows(LPVOID ppEnumProc) state.sclickhwnd = NULL; KillAltSnapMenu(); g_mchwnd = KreateMsgWin(MenuWindowProc, APP_NAME"-SClick"); - + if(!g_mchwnd) return 0; // Failed to create g_mchwnd... // Fill up hwnds[] with the stacked windows. numhwnds = 0; HWND mdiclient = state.mdiclient; @@ -3470,11 +3471,11 @@ static DWORD WINAPI TrackMenuOfWindows(LPVOID ppEnumProc) MENUITEMINFO lpmi= { sizeof(MENUITEMINFO) }; lpmi.fMask = MIIM_DATA|MIIM_TYPE|MIIM_ID; lpmi.fType = MFT_OWNERDRAW; /*MFT_STRING*/ - lpmi.wID = i; + lpmi.wID = i+1; // Id starts at 1 because 0 is for ESCAPE. lpmi.dwItemData = (ULONG_PTR)&data[i]; lpmi.dwTypeData = (LPWSTR)&data[i].msaa; lpmi.cch = sizeof(MSAAMENUINFO); - InsertMenuItem(menu, i, FALSE, &lpmi); + InsertMenuItem(menu, i+1, FALSE, &lpmi); } POINT pt; GetCursorPos(&pt); @@ -3484,13 +3485,13 @@ static DWORD WINAPI TrackMenuOfWindows(LPVOID ppEnumProc) , pt.x, pt.y, 0, g_mchwnd, NULL); state.mdiclient = mdiclient; LOG("menu=%u", i); - SetForegroundWindowL(hwnds[i]); + // if the return value is in the range.. + if (0 < i && i <= numhwnds) + SetForegroundWindowL(hwnds[i-1]); DestroyMenu(menu); - state.unikeymenu = NULL; DestroyWindow(g_mchwnd); g_mchwnd = NULL; - state.sclickhwnd = NULL; free(data); return 0; @@ -3498,7 +3499,7 @@ static DWORD WINAPI TrackMenuOfWindows(LPVOID ppEnumProc) static void ActionStackList(LPARAM lasermode) { DWORD lpThreadId; - struct TrackMenuOfWindowsparam param; + static struct TrackMenuOfWindowsparam param; param.EnumProc = EnumStackedWindowsProc; param.lp = lasermode; // param.hwnd = state.hwnd; @@ -3539,6 +3540,7 @@ static void ActionMenu(HWND hwnd) // Single click commands static void SClickActions(HWND hwnd, enum action action) { + LOG("Going to perform action %d", (int)action); if (action==AC_MINIMIZE) MinimizeWindow(hwnd); else if (action==AC_MAXIMIZE) ActionMaximize(hwnd); else if (action==AC_CENTER) CenterWindow(hwnd); @@ -4373,6 +4375,7 @@ LRESULT CALLBACK MenuWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara // LOGA("WM_MENUCHAR: %X", wParam); // Turn the input character into a menu identifier. WORD cc = LOWORD(wParam); + if (cc==VK_ESCAPE) return MNC_CLOSE<<16; // Lower case the input character. TCHAR c = (TCHAR)( cc | ((cc - 'A' < 26)<<5) ); WORD item; @@ -4393,7 +4396,7 @@ LRESULT CALLBACK MenuWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara state.sclickhwnd = NULL; } else if (msg == WM_DESTROY) { LOG("Destroying Menu window!"); - if (state.sclickhwnd == fhwndori && IsWindow(fhwndori)) { + if (fhwndori && state.sclickhwnd == fhwndori && IsWindow(fhwndori)) { // Restore the old foreground window SetForegroundWindow(fhwndori); } @@ -4824,6 +4827,7 @@ __declspec(dllexport) void Load(HWND mainhwnd) WNDCLASSEX wnd; memset(&wnd, 0, sizeof(wnd)); wnd.cbSize = sizeof(WNDCLASSEX); +// wnd.style = CS_OWNDC|CS_SAVEBITS; //conf.TransWinOpacity?0:CS_SAVEBITS; wnd.lpfnWndProc = DefWindowProc; wnd.hInstance = hinstDLL; wnd.hbrBackground = CreateSolidBrush(color[0]); @@ -4875,7 +4879,7 @@ __declspec(dllexport) void Load(HWND mainhwnd) // Lobyte is the virtual key code and hibyte is the mod_key if(!RegisterHotKey(g_hkhwnd, 0xC000 + ac, HIBYTE(HK), LOBYTE(HK))) { // LOG("Error registering hotkey %s=%x", action_names[ac], (unsigned)HK); - wchar_t title[256]; + wchar_t title[128]; wcscpy(title, APP_NAME": unable to register hotkey for action "); wcscat(title, txt); ErrorBox(title); From 6efa78803ccff881fdce04388f7dc798f35c1733 Mon Sep 17 00:00:00 2001 From: RamonUnch <74856804+RamonUnch@users.noreply.github.com> Date: Wed, 31 Aug 2022 15:26:05 +0100 Subject: [PATCH 4/4] Add files via upload --- config.c | 34 +++++++++++++++++++++++----------- hooks.c | 12 +++++++----- unfuck.h | 30 +++++++++++++++++------------- 3 files changed, 47 insertions(+), 29 deletions(-) diff --git a/config.c b/config.c index 2ee29fd6..d57c00b7 100644 --- a/config.c +++ b/config.c @@ -867,8 +867,13 @@ static LRESULT WINAPI PickShortcutWinProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM VK_LWIN, VK_RWIN , '\0' }; +// static int was_enabled; switch (msg) { +// case WM_CREATE: { +// was_enabled = ENABLED(); +// if (was_enabled) UnhookSystem(); +// } break; case WM_CHAR: case WM_SYSKEYDOWN: case WM_SYSKEYUP: @@ -903,6 +908,7 @@ static LRESULT WINAPI PickShortcutWinProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM HWND sethwnd = GetDlgItem(phwnd, IDC_SHORTCUTS_SET); EnableWindow(sethwnd, TRUE); SetFocus(sethwnd); +// if (was_enabled) HookSystem(); } break; default: return DefWindowProc(hwnd, msg, wp, lp); @@ -1416,10 +1422,12 @@ LRESULT CALLBACK TestWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara } break; case WM_PAINT: { + /* We must keep track of pens and delete them.*/ RECT wRect; - HPEN pen = (HPEN) CreatePen(PS_SOLID, 2, GetSysColor(COLOR_BTNTEXT)); + const HPEN pen = (HPEN) CreatePen(PS_SOLID, 2, GetSysColor(COLOR_BTNTEXT)); PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); + int SavedCD = SaveDC(hdc); GetWindowRect(hwnd, &wRect); POINT Offset = { wRect.left, wRect.top }; @@ -1444,16 +1452,16 @@ LRESULT CALLBACK TestWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara , width , (height+height*centerfrac/100)/2 + Offset.y); if (centermode == 3) { - HPEN rcpen = (HPEN) CreatePen(PS_SOLID, 2, GetSysColor(COLOR_BTNFACE)); - SelectObject(hdc, rcpen); + HPEN bgpen = (HPEN) CreatePen(PS_SOLID, 2, GetSysColor(COLOR_BTNFACE)); + HPEN prevpen = SelectObject(hdc, bgpen); Rectangle(hdc , Offset.x+(width-width*centerfrac/100)/2 , Offset.y+(height-height*centerfrac/100)/2 , (width+width*centerfrac/100)/2 + Offset.x , (height+height*centerfrac/100)/2 + Offset.y); - DeleteObject(rcpen); - - SelectObject(hdc, pen); + SelectObject(hdc, prevpen); // restore pen + DeleteObject(bgpen); // delete bgpen. + // Draw diagonal lines POINT pta[2] = {{Offset.x+(width-width*centerfrac/100)/2, Offset.y+(height-height*centerfrac/100)/2}, { (width+width*centerfrac/100)/2 + Offset.x, (height+height*centerfrac/100)/2 + Offset.y} }; @@ -1463,19 +1471,18 @@ LRESULT CALLBACK TestWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara }; Polyline(hdc, ptb, 2); - rcpen = (HPEN) CreatePen(PS_DOT, 1, GetSysColor(COLOR_BTNTEXT)); - SelectObject(hdc, rcpen); + HPEN dotpen = (HPEN) CreatePen(PS_DOT, 1, GetSysColor(COLOR_BTNTEXT)); + prevpen = SelectObject(hdc, dotpen); SetBkColor(hdc, GetSysColor(COLOR_BTNFACE)); Rectangle(hdc , Offset.x+(width-width*centerfrac/100)/2 , Offset.y+(height-height*centerfrac/100)/2 , (width+width*centerfrac/100)/2 + Offset.x , (height+height*centerfrac/100)/2 + Offset.y); - DeleteObject(rcpen); + SelectObject(hdc, prevpen); // restore pen + DeleteObject(dotpen); // so we can delete this one... } - DeleteObject(pen); - // Draw textual info.... SetBkMode(hdc, TRANSPARENT); SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT)); @@ -1489,7 +1496,12 @@ LRESULT CALLBACK TestWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara RECT trc2 = {5, 5, crc.right, splitheight}; DrawText(hdc, str, wcslen(str), &trc2, DT_NOCLIP|DT_TABSTOP); } + + RestoreDC(hdc, SavedCD); EndPaint(hwnd, &ps); + + DeleteObject(pen); // delete pen + return 0; } break; diff --git a/hooks.c b/hooks.c index b4b8f8c4..0fb68da1 100644 --- a/hooks.c +++ b/hooks.c @@ -1102,9 +1102,11 @@ static void MoveResizeWindowThread(struct windowRR *lw, UINT flag) // Use Restore RestoreWindowTo(hwnd, lw->x, lw->y, lw->width, lw->height); } else { -// RECT rc = { lw->x, lw->y, lw->x + lw->width, lw->y + lw->height }; // PostMessage(hwnd, WM_MOUSEMOVE, MK_LBUTTON, MAKELPARAM(state.prevpt.x, state.prevpt.y)); -// if(!(flag&SWP_NOSIZE)) SendMessage(hwnd, WM_SIZING, WMSZ_BOTTOMRIGHT, (LPARAM)&rc); +// if(!(flag&SWP_NOSIZE)) { +// RECT rc = { lw->x, lw->y, lw->x + lw->width, lw->y + lw->height }; +// SendMessage(hwnd, WM_SIZING, WMSZ_BOTTOMRIGHT, (LPARAM)&rc); +// } SetWindowPos(hwnd, NULL, lw->x, lw->y, lw->width, lw->height, flag); // Send WM_SYNCPAINT in case to wait for the end of movement @@ -3239,7 +3241,7 @@ static LRESULT CALLBACK PinWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) // Move and size the window... SetWindowPos(hwnd, NULL , rc.right-data->rightoffset, rc.top+data->topoffset, PinW, PinH - , SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOOWNERZORDER); + , SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOCOPYBITS); return 0; } break; case WM_PAINT: { @@ -3249,8 +3251,9 @@ static LRESULT CALLBACK PinWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) RECT cr; GetClientRect(hwnd, &cr); BeginPaint(hwnd, &ps); - SetBkMode(ps.hdc, TRANSPARENT); + int oldBkMode = SetBkMode(ps.hdc, TRANSPARENT); DrawTextW(ps.hdc, &Topchar, 1, &cr, DT_VCENTER|DT_CENTER|DT_SINGLELINE); + SetBkMode(ps.hdc, oldBkMode); // restore BkMode EndPaint(hwnd, &ps); } } break; @@ -4827,7 +4830,6 @@ __declspec(dllexport) void Load(HWND mainhwnd) WNDCLASSEX wnd; memset(&wnd, 0, sizeof(wnd)); wnd.cbSize = sizeof(WNDCLASSEX); -// wnd.style = CS_OWNDC|CS_SAVEBITS; //conf.TransWinOpacity?0:CS_SAVEBITS; wnd.lpfnWndProc = DefWindowProc; wnd.hInstance = hinstDLL; wnd.hbrBackground = CreateSolidBrush(color[0]); diff --git a/unfuck.h b/unfuck.h index fb4a32cc..6862090e 100644 --- a/unfuck.h +++ b/unfuck.h @@ -388,7 +388,7 @@ static LRESULT GetDpiForMonitorL(HMONITOR hmonitor, int dpiType, UINT *dpiX, UIN if (myGetDpiForMonitor) { /* We know we have the function */ return myGetDpiForMonitor(hmonitor, dpiType, dpiX, dpiY); } - return 666; // Fail with 666 error + return 666; /* Fail with 666 error */ } /* Supported wince Windows 10, version 1607 [desktop apps only] */ @@ -518,8 +518,8 @@ static BOOL IsVisible(HWND hwnd) return IsWindowVisible(hwnd) && !IsWindowCloaked(hwnd); } -// Gets the original owner of hwnd. -// stops going back the owner chain if invisible. +/* Gets the original owner of hwnd. + * stops going back the owner chain if invisible. */ static HWND GetRootOwner(HWND hwnd) { HWND parent; @@ -528,9 +528,13 @@ static HWND GetRootOwner(HWND hwnd) ? GetParent(hwnd) : GetWindow(hwnd, GW_OWNER) )) { - if (parent == hwnd || i++ > 2048 || !IsVisible(parent)) - break; // stop if in a loop or if parent is no more visible - + RECT prc; + if (parent == hwnd || i++ > 2048 || !IsVisible(parent) + || !GetWindowRect(parent, &prc) || IsRectEmpty(&prc)) { + /* Stop if in a loop or if parent is not visible + * or if the parent rect is empty */ + break; + } hwnd = parent; } @@ -678,15 +682,15 @@ static HICON GetWindowIcon(HWND hwnd) HICON icon; if (SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL, 0, SMTO_ABORTIFHUNG, TIMEOUT, (PDWORD_PTR)&icon)) { /* The message failed without timeout */ - if (icon) return icon; // Sucess + if (icon) return icon; /* Sucess */ - // ICON_SMALL2 exists since Windows XP only + /* ICON_SMALL2 exists since Windows XP only */ static BYTE WINXP_PLUS=0xFF; if (WINXP_PLUS == 0xFF) { WORD WinVer = LOWORD(GetVersion()); BYTE ver = LOBYTE(WinVer); BYTE min = LOBYTE(WinVer); - WINXP_PLUS = ver > 5 || (ver == 5 && min > 0); // XP is NT 5.1 + WINXP_PLUS = ver > 5 || (ver == 5 && min > 0); /* XP is NT 5.1 */ } if (WINXP_PLUS && SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL2, 0, SMTO_ABORTIFHUNG, TIMEOUT, (PDWORD_PTR)&icon) && icon) @@ -696,10 +700,11 @@ static HICON GetWindowIcon(HWND hwnd) if (SendMessageTimeout(hwnd, WM_GETICON, ICON_BIG, 0, SMTO_ABORTIFHUNG, TIMEOUT, (PDWORD_PTR)&icon) && icon) return icon; } - // Try the Class icon if nothing can be get through + /* Try the Class icon if nothing can be get */ if ((icon = (HICON)GetClassLongPtr(hwnd, GCLP_HICONSM))) return icon; if ((icon = (HICON)GetClassLongPtr(hwnd, GCLP_HICON))) return icon; - return LoadIcon(NULL, IDI_WINLOGO); + + return LoadIcon(NULL, IDI_WINLOGO); /* Default to generic window icon */ #undef TIMEOUT } /* Helper function to get the current system menu font. @@ -752,9 +757,8 @@ static HFONT GetNCMenuFont(UINT dpi) BOOL ret = SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, sizeof(struct NEWNONCLIENTMETRICSW), &ncm, 0, dpi); if (!ret) { /* Old Windows versions... XP and below */ ncm.cbSize = sizeof(struct OLDNONCLIENTMETRICSW); - SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0); + SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(struct OLDNONCLIENTMETRICSW), &ncm, 0); } -// LOGA("Menu Font: %ld, %S", ncm.lfMenuFont.lfHeight, ncm.lfMenuFont.lfFaceName); return CreateFontIndirect(&ncm.lfMenuFont); }