How to make "Browse/save file as" dialog show over NSMainMenuWindowLevel - objective-c

I had the need to create a window so it covers the menubar at top and the dock at bottom. So I had to [NSWindow setLevel:NSMainMenuWindowLevel+1] (if i did just NSMainMenuWindowLevel some of the corner items in the top right of the menubar would still show over my window so I had to go +1).
So now the issue is, a user right clicks in my window (which is a canvas drawing of an image) and then they select "save as", at this point I pop open the "Save as" dialog, but it is showing behind my window. Is there anyway to like find that just opened dialog window with objc and set its level to be above NSMainMenuWindowLevel+1?
Like is there anyway to make this panel open higher then this level:
var NSSavePanel = objc_getClass('NSSavePanel');
var savePanel = sel_registerName('savePanel');
var aSavePanel = objc_msgSend(NSSavePanel, savePanel);
var runModal = sel_registerName('runModal')
Thanks

You have to defer the setting of the save panel's level until after the window is showing, which is tricky. You can do something like this (in Objective-C) before the call to -runModal:
dispatch_async(dispatch_get_main_queue(), ^{
[[NSApp modalWindow] setLevel:NSMainMenuWindowLevel+1];
});
If you can't use GCD, you can use -performSelector:withObject:afterDelay: with a 0 delay. You'll have to use the selector of a method of your own. (You can't use #selector(setLevel:) because that takes a scalar, not an object, as its parameter.)

Related

Java FX Dialog "appears" with no size

I'm using JFX 11 on Fedora 33 (GNU/Linux) with the Xorg GUI server (v 1.20.11), creating a dialog thus (kotlin):
fun YNdialog (txt : String) : Boolean {
val dlog = Dialog<ButtonType>()
dlog.dialogPane.apply {
contentText = txt
buttonTypes.apply {
add(ButtonType.OK)
add(ButtonType.CANCEL)
}
minWidth = 200.0
minHeight = 100.0
}
dlog.initOwner(theStage.scene.window)
val r = dlog.showAndWait()
return r.isPresent && r.get() == ButtonType.OK
}
This is called from an EventHandler<ActionEvent> associated with a Button:
if (YNdialog("hello world")) ...
There does seem to be a window created. If I remove the initOwner() call, an icon for it appears in the desktop taskbar (KDE), allowing me to do things like move it, but "maximize" and "resize" are greyed out, and the mouse cursor appears to be dragging nothing, ie., it has no width or height.
With the initOwner() it does much the same thing, except it gets no taskbar icon. Also, there is a visible vertical line one or two pixels thick where it should be (centered over the main window). What's more interesting is a second close button appears in the titlebar of the main window:
This is not part of the javafx interface, but I've never seen the window manager (?) do this before.
Occasionally (maybe one in five or ten times) the dialog does appear, and curiously,
the close button there is offset with space for a second one:
When this happens and I can dismiss the dialog window, the second close button on the main window disappears.
Using Alert
Replacing that function, etc. with:
Alert(Alert.AlertType.CONFIRMATION, "hello world").showAndWait()
.filter { res -> res == ButtonType.OK }
.ifPresent { _ -> log.msg("ok!") }
The result is identical to the YNdialog with initOwner().
Am I missing something here? I got all of this pretty much straight from the docs. I have done custom popup windows (instantiated via FXMLLoader) and have not had any problem with that. Does this experience imply the dialog hierarchy is glitchy in this context and I should roll my own?

Support closing of a NSWindow presented as sheet via escape key

How do I setup an NSWindows (on OS X) to be closed when the user presses the escape key?
The window is presented as a sheet via
presentingWindow.beginSheet(mySheetWindow, completionHandler:nil)
It has a close button (via IB) that has a key equivalent set to 'escape'. This close button is already working
Pressing escape leads to the system audio error output ('Funk' - Sound), but no logging and no closing of the window.
You have to add a regular button and position it at the top left corner of your window. Set your button width and alpha to 0.
Click at the key equivalent field and press ESC. It will show the escape key icon
Then create your IBAction for the hidden button as follow:
#IBAction func closeWindowAction(sender: AnyObject) {
window.close()
}
Make sure you have your window outlet connected to the proper window:
#IBOutlet weak var window: NSWindow!

Custom context menu XAML for WP8

I try to implement a custom ContextMenu in a LongListSelector.
I'm not using the ContextMenu from Microsoft.Phone.Controls.Toolkit, it's basically the same as in the Rowi App:
(source: hiddenpineapple.com)
Approach 1
My list item toggles a VisualState on hold and an overlay is shown with controls in it.
The problem
I can't find a way to go back to the default state when the user clicks outside of the list item (as in the default ContextMenu).
Approach 2
I've implemented a custom template for the toolkit ContextMenu which looks exactly the same. I had to move its margin top to -itemHeight, as by default it is below the item.
The problem
The problem with this solution is, that it automatically closes itself when opening and I couldn't figure out how to avoid this.
Another problem was that it didn't work well with TiltEffect.IsTiltEnabled from the Toolkit (visual problems).
I need your help
Any suggestions on how to get this working?
Answer
Thanks to Cheese, now I know how to properly close the menu when the user clicks outside.
His suggestion was to get the coordinates of a Tap event on the current page, and check if it's inside the menu. When not, close the menu.
So I added a Tap listener to the page when the menu opens, and removed it when the menu closes. From the page listener I got the event coordinates and could check if it's inside the control which holds the menu (same size and position). I received the position of the control with Point leftUpperPoint = control.TransformToVisual(page).Transform(new Point(0, 0)) and the rightLowerPoint by adding the ActualWidth and ActualHeight.
But then I realized:
Why should I even calculate if the tap is inside the menu? I always want to close the menu when the user taps anywhere on the screen. If it's outside, yes. If it's on a menu button, yes.
Another modification I made was to listen for MouseLeftButtonDown instead of Tap as it also triggers when the user swipes.
So I removed this code and came up with the following:
private void ToggleMenu(object sender, System.Windows.Input.GestureEventArgs e)
{
PhoneApplicationFrame frame = ((PhoneApplicationFrame)Application.Current.RootVisual);
VisualState state = this.States.CurrentState;
if (state == null || state.Name == "DefaultState")
{
frame.MouseLeftButtonDown += MouseDownDelegate;
this.State = "MenuState";
}
else
{
frame.MouseLeftButtonDown -= MouseDownDelegate;
this.State = "DefaultState";
}
}
private void MouseDownDelegate(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
ToggleMenu(sender, null);
}
This works perfectly!
Thanks to Cheese for the hint.
Something like this by #denniscode http://dotnet.dzone.com/articles/rowi-show-tap-menu
Approach 1 problem
The best solution would be:
Get the menus coordinates, when user makes a tap - you check are tap coordinates on menu or not, if not - dissmiss - simple.
Approach 2 problem
I guess you had some button in a corner and when you tapped on it - nothing happened? And when you dissmissed the Tilt all worked. It seems that tilt works faster than a click, so, tilt changes the button coordinates, and device thiks you have missed/or dragged off
You can use what #ScottIsAFool suggested and maybe create another Dependency Property on your TapMenu control of type UIElement named CloseWhenTappedElement and automatically listen for Tap events inside your control once set. For example
<Grid x:Name="TapArea"/>
<TapMenu CloseWhenTappedElement="{Binding ElementName=TapArea"}/>

makeKeyAndOrderFront doesn't do either

I've got an application that runs at startup as a menu in the OS X menu bar (i.e., as a background application). When you select an option from the menu, it transforms into a foreground application (creating a dock icon) and shows a window.
Here's the background/foreground code I'm using:
+(void) TransformToForegroundApplication {
ProcessSerialNumber psn = { 0, kCurrentProcess };
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
}
+(void) TransformToBackgroundApplication {
ProcessSerialNumber psn = { 0, kCurrentProcess };
TransformProcessType(&psn, kProcessTransformToUIElementApplication);
}
Pretty standard stuff, from the looks of things. And it works fine, except for one small issue.
The problem is that after I call TransformToForegroundApplication, I call makeKeyAndOrderFront: on the window to make it come to the front of the Z-order and receive focus - but it does neither. It shows up in the background, underneath everything else. I need to either click on the dock icon, or minimize all of the windows in front of it and then click on that window, in order to bring it to the front.
Any ideas?
Probably you need to activate the application, which I presume TransformProcessType() will not do automatically, and know -makeKeyAndOrderFront: will not.
Have you tried calling [NSApp activateIgnoringOtherApps:YES]?

How to show a Safari Extension popover programmatically

I'm trying to write a Safari extension that consists of a button on the main toolbar with a popover tied to it, and a contextual menu item. The basic feel is modeled after the feel of the 1Password extension.
One of the jobs of the popover is to allow a person to log in. I'm also conditionally changing the action of the contextual menu item, and if a who person isn't logged in clicks the menu item I would like to show the popover allowing them to log in, but I can't find a way to do this in the developer guides.
How do I "show" a popover?
If you only have one toolbar item and one popover (and never plan to add more), then it's just one line. Assuming you've already assigned the popover to the toolbar item in Extension Builder, you can just use:
safari.extension.toolbarItems[0].showPopover();
But if you have more than one popover and (potentially) more than one toolbar item, here's a generalized function to open a popover, specified by its identifier, under the specified toolbar item in the active browser window:
function showPopover(popoverId, toolbarItemId) {
var toolbarItem = safari.extension.toolbarItems.filter(function (tbi) {
return tbi.identifier == toolbarItemId && tbi.browserWindow == safari.application.activeBrowserWindow;
})[0];
var popover = safari.extension.popovers.filter(function (po) {
return po.identifier == popoverId;
})[0];
toolbarItem.popover = popover;
toolbarItem.showPopover();
}