How to show a window without stealing focus on macOS?
I've been playing around with this a bit, and I seem to be able to produce this effect when the frontmost window is not from the same process as the frontmost application, which is what I suspect Spotlight is probably doing. I can achieve this like so:
Set LSUIElement to YES in my app's Info.plist.
In Interface Builder, set the window's class to NSPanel, check "Non Activating" in the Attributes Inspector, and set "isFloatingPanel" to YES in the User Defined Runtime Attributes under the Identity Inspector.
During some time that some other application is in front (I just used a 5-second delay to give myself time to pop some other app to the front and select a text field), call
makeKeyAndOrderFront()
followed byorderFrontRegardless()
on the window.
When I do this, I get the following (note the focus ring still drawn on Xcode's "Module" field):
Is it possible to move windows in background (without stealing focus)
Open 2 windows (or more) in Safari and try this. It will move the 2nd window 5 pixels to the right. This code should work for your application as well as System Events knows about the windows and can reposition them of other applications. Note that windows also have a size property you may want to use.
tell application "System Events"
tell process "Safari"
set theWindows to windows
if (count of theWindows) is greater than or equal to 2 then
set p to position of (item 2 of theWindows)
set position of window 2 to {(item 1 of p) + 5, item 2 of p}
end if
end tell
end tell
Show Window without activating (keep application below it active)
Either one of these should do the trick:
- Use
-[NSWindow orderFrontRegardless]
to get a normal level window to the front without activating the corresponding app, or - Use
-[NSWindow setLevel:]
to increase the window level to something higher thanNSNormalWindowLevel
How to keep a Form always on top without stealing focus from the active Window?
- Make a standard Form, set its
FormBorderStyle = none
. Make it TopMost (this setting is another topic per se, I'm no going to discuss it here). - Override CreateParams to set the
WS_EX_NOACTIVATE
andWS_EX_TOOLWINDOW
extended styles. This prevents the Form from being activated when mouse events are generated inside its surface (see the docs about these styles). - Add some non-selectable Button Controls to it (the
ButtonNoSel
Control shown below) and set theirTag
property to the Unicode char corresponding to the Emoji image these buttons show. - Add the same Click handler to all the Buttons.
These Buttons, when clicked, simply use SendKeys::Send() (a.k.a. SendInput()
) to send the selected Unicode char to the foreground Window, casting to string the Tag
property value.
This is how it works (setting the Emoji to a Web Page shown by FireFox):
using namespace System;
using namespace System::ComponentModel;
using namespace System::Windows::Forms;
using namespace System::Drawing;
public ref class frmKeyBoard : public System::Windows::Forms::Form
{
public:
frmKeyBoard(void) { InitializeComponent(); }
// [...] Initialization...
protected:
property System::Windows::Forms::CreateParams^ CreateParams {
virtual System::Windows::Forms::CreateParams^ get() override {
auto cp = Form::CreateParams;
cp->ExStyle |= (WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW);
return cp;
}
}
// Event handler for all the Buttons
private:
System::Void buttonNoSelAll_Click(System::Object^ sender, System::EventArgs^ e) {
Control^ ctl = safe_cast<Control^>(sender);
SendKeys::Send(ctl->Tag->ToString());
}
};
Add this simple Custom Control to the Project.
This Control simply uses Control.SetStyle, setting ControlStyles::Selectable = false
to prevent the child Control to become the ActiveControl when interacted with, since it doesn't receive the focus.
using namespace System;
using namespace System::Windows::Forms;
using namespace System::ComponentModel;
namespace CustomControls {
[ToolboxItem(true)]
public ref class ButtonNoSel : public System::Windows::Forms::Button
{
public:
ButtonNoSel(void) {
this->InitializeComponent();
this->SetStyle(ControlStyles::Selectable, false);
}
private:
void InitializeComponent(void) {
this->UseVisualStyleBackColor = true;
}
protected:
~ButtonNoSel() { }
};
}
Note that this Form must run on its own thread.
If you need to show this Form from another one, use Task.Run() to show it as a Dialog Window, calling ShowDialog()
. This will start the Message Loop.
For example, from a Button.Click
handler of another Form (here, named MainForm
).
private:
void ShowKeyboard() {
frmKeyBoard^ fk = gcnew frmKeyBoard();
fk->ShowDialog();
delete fk;
}
private:
System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
Task::Run(gcnew Action(this, &MainForm::ShowKeyboard));
}
Show window in Qt without stealing focus
It took me a while to find it but I found it: setAttribute(Qt::WA_ShowWithoutActivating);
This forces the window not to activate. Even with the Qt::WindowStaysOnTopHint
flag
wxPython on Mac OS X: creating a wx.Frame without stealing focus
If you want to get native handle to window in Mac you can do
frame.MacGetTopLevelWindowRef()
and may be you can use pyobjc to interact with windows natively, but why don't you set focus on the window you want to after opening mini-frame?
Related Topics
What Is the Type of the Logical Operators
Subtle Cast Warning When Using SQLite.Swift ... Binding? to Any
How to Find Max Value for Double and Float in Swift
Does the Order of Subscribeon and Observeon Matter
No Such Module 'Cocoa' in Swift Playground
Creating Baseview Class in Swiftui
Xcode Playgrounds Can't Access Swift Files in Sources Folder
Why Can't I Mutate a Variable Initially Set to a Certain Parameter When the Func Was Called
Physics Detecting Collision Multiple Times
Google API - Invalid Credentials
What's the Best Way to Iterate Over Results from an API, and Know When It's Finished
How to Change Navigationbar Font in Swift
How to Generate Random Numbers Without Repetition in Swift