My application has "Bring to current desktop" option in indicator menu. Now, moving windows across workspaces is nice and easy if you are not using Compiz.
My question is how could I bring application window to current desktop. Application is written in Python and GTK+. I tried using Present method of gtk.Window but then window grabs focus and nothing else happens (window is not actually presented to user). I also tried playing with wnck, but that method works only when Compiz is not running.
Any idea?
Related
Using PyCharm, Python 3.10, MacBook M1 Monterey
I have a module I wrote to produce a plot. It uses a dialog to create a modal window. It works fine, but the position of the window is hard wired in the code. I can move the window manually but if I close the dialog and start another (refreshing the data) it starts at the default position. I want to be able to move a window and have the next refresh appear at the same position. To do that I need the position of the window when it is closed. My approach was to generate a function that stores the position when the window is moved and use that parameter when the window is closed.
The windows is generated by wx.Dialog. I have tried Bind(wx.EVT_MOVE_END...) but although the bound function is executed when the window is generated, moving the window does not generate a move event.
I started writing Python code in Win10 and had no problems with binding functions but when I got the MacBook, I was unable to get keyboard events to work using Bind(wx.EVT_CHAR_HOOK,...) so it appears that there's something different about MacOS and events in Python. I solved the keyboard problem by adding buttons to the dialog to generate the events that I could generate with keystrokes in Win10. I consider this workaround to be a kluge that indicates that something is not working the way I expect (maybe because I'm a beginner and doing self-study [where 'study' -> error and trial]).
Does anyone know why keyboard events and move events do not work in MacOS? I have no problem with EVT_BUTTON, EVT_TIMER, and EVT_LEFT_DOWN.
https://docs.wxpython.org/wx.MoveEvent.html says that EVT_MOVE should work but EVT_MOVE_END is wxMSW only (I assume that means MicroSoftWindows only?). So I tried wx.EVT_MOVE to no avail.
.
.
.
self.Bind(wx.EVT_MOVE_END,self.MovePlot(self))
def MovePlot(self,parent):
PlotPosition = parent.GetPosition()
print('MovePlot Position', PlotPosition)
gp.PlotPosition=PlotPosition
print('parent',parent,parent.Title,parent.ScreenPosition)
.
.
.
In re-reading the link referenced above I find the possible explanation:
"These events are currently generated for top level (see wx.TopLevelWindow) windows in all ports, but are not generated for the child windows in wxGTK."
So now the question becomes "How do I get an event handler for a child window?"
And "Why does the keyboard event work in Win10 but not in MacOS?"
I'm using the latest version (to date) of pywinauto; and also using PyInspect (uia) to identify controls.
I'm automating controls on an application, and part of the process is to check a few boxes on a window that pops up after triggering the window to appear from a menu selection (like Edit->Settings).
The problem is, pywinauto doesn't seem to be able to detect the new window. I see successfully opens; and can see the window and elements as a sub (child?) window of the application in PyInspect.
I've tried wait methods, thinking the automation is occurring too fast- but to no avail. something like:
mysettings = app['app-name'].child_window(title_re="my target settings window", class_name="#32770").wait('exists', timeout=10)
this will just timeout. And if I print control identifiers, "my target settings window" is never included.
app['app-name'].print_control_identifiers()
I also tried set_focus on top_window.. that didn't work either. My conclusion is that pywinauto is having trouble detect that it is there. Any thoughts on this?
I was able to resolve this issue of pywinauto detecting the child window, and the issue that immediately followed: accessing the child window.
First, I was able to get pywinauto to detect the new window by defining backend='uia' in the application definition, like this:
app = application.Application(backend='uia')
I previously just had:
app = application.Application()
My next issue was accessing elements on the child window. I could not access the window directly, as I may have anticipated:
app['my app']['child window']['textbox'].set_edit_text("hello world")
Instead, this code worked:
app['my app'].child_window(title='child window name').Edit1.set_edit_text("hello world")
While I have resolved my issue, I have noticed that after defining backend='uia', the process now executes much slower than before. If anyone who stumbles across this has any feedback in that regard (or optimizing my efforts above), please contribute.
Thanks
I created a PyGTK application which needs to be always on top. The transparent window redirects mouse clicks to the window below and therefore gets out of focus once you click into an underlaying window. This is the intended behaviour. In fact it should just show a little image that's always above everything.
This works well unless you use something like the libreoffice fullscreen presentation. The presentation window is marked as always on top as well and hence my window goes into the background. Even if I take it to front using Alt+Tab and then click onto the underlaying libreoffice slide (which is neccessary) my window goes into the background again.
This is a really specific question and the solution should work on both Linux and Windows. I have no idea what I should do. I just found many questions on how to have a windows always on top but none of them covering my problem.
Long story short: How can I put my window always on top of every window that is always on top as well?
Simple Answer: You can use 'Always on Top' in windows with by using AutoHotKey scripts.
Follow these steps:
Install AutoHotKey
Create a new AHK scripts following the images
Add this code ^SPACE:: Winset, Alwaysontop, , A
Next, double-click your script to run it. You’ll know it’s running
because a green “H” logo appears in your system tray to let you know
it’s running as a background process.
Now press Ctrl+Space to set any currently active window to be always
on top. Press Ctrl+Space again set the window to no longer be always
on top.
I am writing a wxPython application that remains open after closing all of its windows - so you can still drag & drop new files onto the OSX dock icon (I do this with myApp.SetExitOnFrameDelete(False)).
Unfortunately if I close all the windows, the OSX menubar will only contain a "Help" menu. I would like to add at least a File/Open menu item, or just keep the menubar of the main window. Is this somehow possible in wxPython?
In fact, I would be happy with a non-wxPython hack as well (for example, setting the menu in pyobjc, but running the rest of the GUI in wxPython). wxPython development in OSX is such a hack anyway ;)
UPDATE: I managed to solve this problem using the tip from Lyndsey Ferguson. Here's what I have done:
On startup I create a window which I show and hide immediately. I set its position to (-10000,-10000) so that it does not flicker on the screen (aargh, what a dirty hack!)
I create an empty EVT_CLOSE event handler in that window so that it cannot be closed.
It seems that destroying a window resets the OSX menu, but hiding does not... So when the last window is closed, I need to show and hide this window again (hiding is necessary so that the user cannot switch to this window using the Window menu or Cmd-`)
Yeah, this is really ugly... I will be very grateful if someone comes up with a prettier solution.
UPDATE 2: Actually it can be solved in a much easier way: if we do not close the last window, only hide it. And ensure that it does not respond to menu events anymore.
Nowadays you can use wx.MenuBar.MacSetCommonMenuBar() to set the menu bar (which you have to create) that should be used when no windows are open.
If you just want a default macOS menu bar to be used (with the application and Window menus already there), this appears to be the minimal code:
menubar = wx.MenuBar()
wx.MenuBar.MacSetCommonMenuBar(menubar)
This will let your app respond to Command+Q out-of-the-box, too.
The wx.MenuItem IDs wx.ID_ABOUT and wx.ID_EXIT are special as menu items with those IDs are moved to the macOS Application menu. The docs actually refer to the application menu as the "Apple" menu (e.g. the menu described in the wx.MenuBar.OSXGetAppleMenu() function's docs is the application menu), possibly for historical reasons.
Can you create a hidden window that is offscreen somewhere? It is a hack, but I remember having to do a lot of hacks to make my wxPython-based application work correctly on Mac OS X.
Note:You'll have to disable the close button and set up that hidden window so that it doesn't show up in the Window menu.
Aside:Have you considered factoring out your GUI portion of your Python application and using PyObjC on Mac OS X? You'll get more native behaviours...
The standalone flashplayer takes no arguments other than a .swf file when you launch it from the command line. I need the player to go full screen, no window borders and such. This can be accomplished by hitting ctrl+f once the program has started. I want to do this programmatically as I need it to launch into full screen without any human interaction.
My guess is that I need to some how get a handle to the window and then send it an event that looks like the "ctrl+f" keystroke.
If it makes any difference, it looks like flashplayer is a gtk application and I have python with pygtk installed.
UPDATE (the solution I used... thanks to ypnos' answer):
./flashplayer http://example.com/example.swf & sleep 3 && ~/xsendkey -window "Adobe Flash Player 10" Control+F
You can use a dedicated application which sends the keystroke to the window manager, which should then pass it to flash, if the window starts as being the active window on the screen. This is quite error prone, though, due to delays between starting flash and when the window will show up.
For example, your script could do something like this:
flashplayer *.swf
sleep 3 && xsendkey Control+F
The application xsendkey can be found here: http://people.csail.mit.edu/adonovan/hacks/xsendkey.html
Without given a specific window, it will send it to the root window, which is handled by your window manager. You could also try to figure out the Window id first, using xprop or something related to it.
Another option is a Window manager, which is able to remember your settings and automatically apply them. Fluxbos for example provides this feature. You could set fluxbox to make the Window decor-less and stretch it over the whole screen, if flashplayer supports being resized. This is also not-so-nice, as it would probably affect all the flashplayer windows you open ever.
I've actually done this a long time ago, but it wasn't petty. What we did is use the Sawfish window manager and wrote a hook to recognize the flashplayer window, then strip all the decorations and snap it full screen.
This may be possible without using the window manager, by registering for X window creation events from an external application, but I'm not familiar enough with X11 to tell you how that would be done.
Another option would be to write a pygtk application that embedded the standalone flash player inside a gtk.Socket and then resized itself. After a bit of thought, this might be your best bet.
nspluginplayer --fullscreen src=path/to/flashfile.swf
which is from the [http://gwenole.beauchesne.info//en/projects/nspluginwrapper](nspluginwrapper project)
Another option would be to write a pygtk application that embedded the standalone flash player inside a gtk.Socket and then resized itself. After a bit of thought, this might be your best bet.
This is exactly what I did. In addition to that, my player scales flash content via Xcomposite, Xfixes and Cairo. A .deb including python source be found here:
http://www.crutzi.info/crutziplayer
I've done this using openbox using a similar mechanism to the one that bmdhacks mentions. The thing that I did note from this was that the standalone flash player performed considerably worse fullscreen than the same player in a maximised undecorated window. (that, annoyingly is not properly fullscreen because of the menubar). I was wondering about running it with a custom gtk theme to make the menu invisible. That's just a performance issue though. If fullscreen currently works ok, then it's unneccisarily complicated. I was running on an OLPC XO, performance is more of an issue there.
I didn't have much luck with nspluginplayer (too buggy I think).
Ultimately I had the luxury of making the flash that was running so I could simply place code into the flash itself. By a similar token, Since you can embed flash within flash, it should be possible to make a little stub swf that goes fullscreen automatically and contains the target sfw.
You have to use Acton script 3 cmd:
stage.displayState = StageDisplayState.FULL_SCREEN;
See Adobe Action script 3 programming.
But be careful : in full screen, you will lose display performances!
I've got this problem ... more under Linux!!!