Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/ManagedShell.AppBar/AppBarWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ protected virtual void OnSourceInitialized(object sender, EventArgs e)
helper = new WindowInteropHelper(this);
Handle = helper.Handle;

WindowHelper.SetWindowNoActivate(Handle);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? Generally AppBars should be able to take focus.

Copy link
Contributor Author

@curoviyxru curoviyxru Mar 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it will take a focus, Windows-like layout switcher located on menu bar wouldn't able to switch current layout language for focused window. (because it will take focus for itself)
It doesn't matter when keyboard layout is system-wide in Windows. (but if layout is window-wide that will cause some problems that I had encountered)
We can remember last window that was focused before Cairo and then change it layout, but it will be a strange workaround imo.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taskbar.behavior.mp4
Cairo.behavior.mp4
Cairo.behavior.without.WS_EX_NOACTIVATE.mp4

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AppBar should still take focus (e.g., so you can change the input method for Cairo when searching), what shouldn't take focus is only the input indicator (e.g., so that you can change the input method for the current app window if enabled).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about this way, but how it could be implemented?

p.s. interesting to find out, why it should take focus?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to make sure that the input indicator control does not receive focus when clicked.

If I remember correctly, some AppBars, as in RetroBar, need focus for the windows to be behind the taskbar.


// set up window procedure
HwndSource source = HwndSource.FromHwnd(Handle);
source.AddHook(WndProc);
Expand Down
27 changes: 6 additions & 21 deletions src/ManagedShell.Common/Helpers/KeyboardLayoutHelper.cs
Original file line number Diff line number Diff line change
@@ -1,26 +1,19 @@
using ManagedShell.Common.Structs;
using ManagedShell.Interop;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System;

namespace ManagedShell.Common.Helpers
{
public static class KeyboardLayoutHelper
{
public static KeyboardLayout GetKeyboardLayout(bool currentThread = false)
public static KeyboardLayout GetKeyboardLayout()
{
uint threadId = 0;
if (!currentThread)
threadId = NativeMethods.GetWindowThreadProcessId(NativeMethods.GetForegroundWindow(), out _);
uint threadId = NativeMethods.GetWindowThreadProcessId(NativeMethods.GetForegroundWindow(), out _);
var layout = NativeMethods.GetKeyboardLayout(threadId);

return new KeyboardLayout()
{
HKL = layout,
NativeName = CultureInfo.GetCultureInfo((short)layout).NativeName,
ThreeLetterName = CultureInfo.GetCultureInfo((short)layout).ThreeLetterISOLanguageName.ToUpper()
};
return new KeyboardLayout(layout);
}

public static List<KeyboardLayout> GetKeyboardLayoutList()
Expand All @@ -29,20 +22,12 @@ public static List<KeyboardLayout> GetKeyboardLayoutList()
var result = new long[size];
NativeMethods.GetKeyboardLayoutList(size, result);

return result.Select(x => new KeyboardLayout()
{
HKL = (int)x,
NativeName = CultureInfo.GetCultureInfo((short)x).NativeName,
ThreeLetterName = CultureInfo.GetCultureInfo((short)x).ThreeLetterISOLanguageName.ToUpper()
}).ToList();
return result.Select(x => new KeyboardLayout((int)x)).ToList();
}

public static bool SetKeyboardLayout(int layoutId)
{
return NativeMethods.PostMessage(0xffff,
(uint) NativeMethods.WM.INPUTLANGCHANGEREQUEST,
0,
NativeMethods.LoadKeyboardLayout(layoutId.ToString("x8"), (uint)(NativeMethods.KLF.SUBSTITUTE_OK | NativeMethods.KLF.ACTIVATE)));
return NativeMethods.PostMessage(NativeMethods.GetForegroundWindow(), (int)NativeMethods.WM.INPUTLANGCHANGEREQUEST, IntPtr.Zero, new IntPtr(layoutId));
}
}
}
8 changes: 7 additions & 1 deletion src/ManagedShell.Common/Helpers/WindowHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ public static class WindowHelper
{
public const string TrayWndClass = "Shell_TrayWnd";

public static void SetWindowNoActivate(IntPtr handle)
{
SetWindowLong(handle, GWL_EXSTYLE,
GetWindowLong(handle, GWL_EXSTYLE) | (int) ExtendedWindowStyles.WS_EX_NOACTIVATE);
}

public static void ShowWindowBottomMost(IntPtr handle)
{
SetWindowPos(
Expand All @@ -29,7 +35,7 @@ public static void ShowWindowTopMost(IntPtr handle)
0,
0,
0,
(int)SetWindowPosFlags.SWP_NOSIZE | (int)SetWindowPosFlags.SWP_NOMOVE | (int)SetWindowPosFlags.SWP_SHOWWINDOW/* | (int)SetWindowPosFlags.SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER*/);
(int)SetWindowPosFlags.SWP_NOSIZE | (int)SetWindowPosFlags.SWP_NOMOVE | (int)SetWindowPosFlags.SWP_SHOWWINDOW | (int)SetWindowPosFlags.SWP_NOACTIVATE /* | SWP_NOZORDER | SWP_NOOWNERZORDER*/);
}

public static void ShowWindowDesktop(IntPtr hwnd)
Expand Down
15 changes: 14 additions & 1 deletion src/ManagedShell.Common/Structs/KeyboardLayout.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
namespace ManagedShell.Common.Structs
using System.Globalization;

namespace ManagedShell.Common.Structs
{
public struct KeyboardLayout
{
public int HKL { get; set; }
public string NativeName { get; set; }
public string ThreeLetterName { get; set; }
public string DisplayName { get; set; }

public KeyboardLayout(int hkl)
{
HKL = hkl;
var cultureInfo = CultureInfo.GetCultureInfo((short)hkl);

NativeName = cultureInfo.NativeName;
ThreeLetterName = cultureInfo.ThreeLetterISOLanguageName.ToUpper();
DisplayName = cultureInfo.DisplayName;
}
}
}
5 changes: 4 additions & 1 deletion src/ManagedShell.Interop/NativeMethods.User32.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2997,7 +2997,10 @@ public static extern IntPtr CreateWindowEx(
public static extern int ActivateKeyboardLayout(int hkl, uint flags);

[DllImport(User32_DllName)]
public static extern bool PostMessage(int hWnd, uint msg, int wParam, long lParam);
public static extern bool PostMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

[DllImport(User32_DllName)]
public static extern IntPtr GetTopWindow(IntPtr hWnd);

public enum KLF : uint
{
Expand Down