We have a game at work where if you can send the security guy an email from someone's unlocked computer you get a prize. This Halloween I am setting a trap.
I have a simple program called systems-engage that starts a key listener and opens my inbox programmatically. When someone starts using the keyboard I want my program to launch a full-screen visual assault of horror film images with extremely loud screaming.
I can handle everything else mentioned, I just need a dead simple way to open a full screen window that can only be closed by an escape sequence I define in code.
I'm going for lowest hanging fruit here (Objective-C, C++, Java, python ruby, JavaScript hell whatever gets the job done quick and dirty.
I read a primer on opening a full screen window in Objective-C but it can be closed really easily. The point of this prank is to shame my co-worker for invading my computer for at least 10 or 20 seconds and I can't do that if he can just hit Appl-Q.
Happy Halloween!
To get something like this with a Cocoa app, you can place the following code in your app delegate's - (void)applicationDidFinishLaunching: (or similar):
// Set the key equivalent of the "Quit" menu item to something other than ⌘-Q.
// In this case, ^-⌥-⌘-Q.
// !!! Verify this and make sure you remember it or else you're screwed. !!!
NSMenu *mainMenu = [NSApplication sharedApplication].mainMenu;
NSMenu *appMenu = [[mainMenu itemAtIndex:0] submenu];
NSMenuItem *quitItem = [appMenu itemWithTitle:#"Quit <Your App Name Here>"];
quitItem.keyEquivalentModifierMask = NSEventModifierFlagControl | NSEventModifierFlagOption | NSEventModifierFlagCommand;
quitItem.keyEquivalent = #"q";
// Enable "kiosk mode" -- when fullscreen, hide the dock and menu bar, and prevent the user from switching away from the app or force-quitting.
[NSApplication sharedApplication].presentationOptions = NSApplicationPresentationHideDock
| NSApplicationPresentationHideMenuBar
| NSApplicationPresentationDisableProcessSwitching
| NSApplicationPresentationDisableForceQuit
| NSApplicationPresentationDisableSessionTermination;
// Remove the window's close button, making it no longer close with ⌘-W.
self.window.styleMask = self.window.styleMask & ~NSWindowStyleMaskClosable;
// Make the window take up the whole screen and make it full-screen.
[self.window setFrame:[[NSScreen mainScreen] frame] display:YES];
[self.window toggleFullScreen:self];
This will make a "kiosk" type app which can only be closed via the custom quit shortcut you set (or, you know, shutting down the computer forcibly). The presentation options prevents the user from accessing the menu bar, dock, and app switching (via ⌘-Tab) or spaces, bringing up the force-quit window, or bringing up the shutdown/restart/sleep window. Basically, make sure you set up a keyboard shortcut that you remember to terminate the app, otherwise, you're going to be locked out of your machine short of forcibly powering it off. It's a total PITA.
Of course, some of these customizations can be done in Interface Builder too (setting the key equivalent of the "Quit" menu item is easier there, and you can turn off the window's close control as well, as mentioned in comments above), but I just wanted to include this as code so it was more transparent (rather than uploading an Xcode project).
Happy Halloween! 😈
Related
A python evdev device has a .grab() function that prevents other processes from getting input events on the device. Is there any way to limit this to specific events from a device?
For my example, if I .grab() a pen input device that has pressure sensitivity and tilt and 2 click buttons on the side, how would I 'grab' ONLY the 2 click buttons but let the rest of the input (the tip, pressure sensitivity and tilt) be caught by the rest of the system as normal?
One of my pen buttons is normally a right click mouse event. I want to make it do something else but it still pops up the right click menu so I'm trying to figure out how to stop that.
I tried doing the grab and ungrab when the event occurs. Like event > grab > do my stuff > ungrab. But that is obviously too late and the OS still pops up the menu.
I tried doing the full grab, then in the event loop if it is a button press do my stuff, otherwise create a UInput event injection by just passing the event back to the system. This was a bit of a tangled mess. Permissions are required. When I finally got past that, the movement was offset and the pressure/tilt wasn't working... I think it is something to do with the DigiMend driver that actually makes that stuff work and/or xinput settings I have to pass to calibrate the tablet. But I'm not interested in writing all the pressure/tilt functionality from scratch or anything like that, so I need the DigiMend stuff to work as normal. So I gave up on this idea for now.
The only other thought I had was figure out why the OS defaults to the behavior it does and see if I can just manually disable the actions (i.e. Why does it think that button is a right mouse click and make it think that button is nothing instead.)
So I guess this is a 3 level question.
Can I achieve the the grab functionality on select events instead of the device as a whole?
If the passthrough idea was better, is there a way to achieve this without having to do any permission modifications and be able to pass the exact event (i.e. no offset and such that I experienced?)
If evdev does not have this ability or it'd be easier to do in another way, like disabling the defaults for the pen in the OS somehow, I am open to suggestions. I am using Kubuntu 20.04 if that helps.
Any help would be appreciated, let me know if more info is needed, thanks in advance!
I ended up going with #3 and using xinput. Figured I'd put up this answer for now in case others come across this and want to do something similar.
The workaround was actually kind of simple. I just use xinput to remap the 2 buttons. So evdev doesn't have to grab at all. Just disable those buttons and everything goes normally except those, which I listen for with evdev.
xinput set-button-map {} 1 0 0 4 5 6 7
My device has 7 buttons and are normally mapped 1-7. Which are all mouse equivalents of left click, middle click, right click, etc...
By using that string and passing the device ID in for the {} I just run that with subprocess first. And voila, no more right click menu. And I can use evdev to map the events to whatever I want.
There seems to be a distinct lack of documentation of the GObjects module for python at the moment, so maybe somebody can help me.
I am making an application which occasionally will have to notify the user that an event has occurred. I have found about using from gi.repository import Notify and the relating classes from using a short snippet for skype notifications and the C documentation, but it seems to not close when I call Notify.uninit. The program closes, but the little notification window thing stays put and has to be closed by right clicking on it and selecting "Remove". So, I am wondering if there is perhaps another way like if there was something similar to how in Mac OS the application icon shakes/bounces when something happens or in Windows the application icon glowing a different color?
I like the Gnome 3 notification system with the message stack and such, but since I can't seem to get it to disappear when my application exits I don't really want to use it (unless someone knows how to properly do this...it may be that I forgot to set a timeout, but that still doesn't make sense as to why I can't just make the notification spot disappear).
Calling Notify.uninit is not supposed to make the notifications disappear, it only tells libnotify that it will no longer be needed for your application. To make notifications disappear, you have to close them explicitly like in the following example:
import time
from gi.repository import Notify
Notify.init('myapp')
# optionally set an icon as the last argument
n = Notify.Notification.new('summary text', 'body text', "dialog-information")
n.show()
# do whatever your application is doing
time.sleep(10)
n.close()
Notify.uninit()
I am developing an application that will run on Linux to run fullscreen all the time (no menus or trays or anything will be visible).
The application is going to be developed in Python, not that that matters as far as the window manager, but what I am having a hard time with is choosing a window manager.
I need something with the smallest possible footprint, that will let me run a graphical Python app and have an mplayer window at the same time, at widescreen resolutions (widescreen, 16:10,16:9, etc). Other than that, it doesn't need a lot of features, but the end footprint size is the most important thing I'll be looking at.
What window manager would you recommend?
EDIT: There won't be any interaction with the application needed.
You don't actually need any window manager or display manager. All you need to do is open your initial window with the same geometry as the root window. I suppose you could even draw directly into the root window if you wanted.
If you are using some display library it probably has an easy way to open a full screen window. For example using a recent enough version of SDL through pygame you can do
pygame.display.init()
surface = pygame.display.set_mode((0,0),pygame.FULLSCREEN,0)
to get a window that fills the entire screen. This will work even if there is no window manager running.
As for mplayer, it accepts the -geometry flag, so you can use something like mplayer -geometry 640x480+20+20 to display the mplayer window 20 pixels from the top 20 pixels from the left and with a size of 640x480 pixels.
You probably meant window manager. Display manages are KDM, GDM and the like. Windoe managers, to name, GNOME, Xfce, KDE, ratpoison, fvwm, twm, blackbox are a few. ratpoison gives full screen to the application that is in the foreground but demands heavy keyboard interaction (hence the name ratpoison) and no mouse interaction at all.
I assume you'll be running both your python GUI and mplayer in some sort of geometries combination that shows both at the same time, filling the screen.
As commented, you should not need a window manager to achieve that. You could have your python GUI app get command-line parameters for setting its window geometry and also call fullscreen mplayer with the -geometry parameter. That should fill the screen as expected, without any window decorations.
Now you could have the startx script called for the user running it all and have a custom ~/.xinitrc script doing something like:
#!/bin/sh
exec python my_gui_app --whatever-sets-geom &
exec mplayer -fs video.avi
If yout pyhon app will instead be launching mplayer then just leave the first 'exex' call (remove the '&') and have it call mplayer as desired with the expected dimensions in '-fs' mode.
Please note you may need to use something like the 'xset' program to disable monitor blanking due to energy savings, hide the cursor (although IIRC that's something mplayer does for its own window), and things like that.
Also, somethimes running, for example, GTK apps on a bare X display may end up using an "ugly" theme, so you may need to have the toolkit style configuration taken care of someway.
I am doing something similar on my "set-top box" and I don't use any window manager.
It boots debian, and from inittab I auto-login the user that runs the display. That user's .profile starts X, which runs .xinitrc, which starts my python app that runs as a network server in front of mplayer (running mplayer in -slave mode).
My python app does not have a GUI element - only mplayer runs on the X display. But in your case, it should be no different. As I mentioned in a comment to another answer, you may want to look into how you can reparent mplayer's window to give you greater control over its placement and/or movement/size.
Doing it this way avoided a display manager and a window manager. This simplifies the solution, boots faster and uses a smaller footprint (it runs of an SD card, with heaps of room to spare).
I realize this is an old question, but I use openbox on my system, I have created a custom config file that disables all mouse keyboard shortcuts, and removes borders etc on the applications.
In the openbox config i even created some secret shortcuts that can run fx. an xterm for debugging live on the box.
The openbox documentation was very helpful in figuring everything out, I did the config in about 30 minutes.
I have created a service which display a sort of splash screen on the desktop of a specific user and only when that user is logged in (kiosk user).
That splash screen, once entered a valid code, will tell that to the service and the service goes to sleep for an x amount of time (depending of the code).
The splash screen simply quits. Now when the service wakes up it sees that the splash is no longer there and so start it up.
This all is working, the only problem is that the launched application does not have focus, i.e. if I am working in notepad and the time is up, the splash screen is displayed (full screen though) behind notepad.
I only have to worry about Windows Vista, I am coding in Python using win32 extensions but I believe this problem lies in CreateProcessAsUser when called from the LocalSystem account.
Update:
The 'problem' is actually an on purpose limitation to prevent 'irritating' applications like mine from stealing focus.
You can change the behaviour by setting:
win32gui.SystemParametersInfo(win32con.SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 0)
which is equivalent in temporarily setting the registry value:
HKEY_CURRENT_USER\Control Panel\Desktop\ForegroundLockTimeout
This must be done as the user itself, so either build it in the app you are launching or build an launching helper for the app you want to launch.
However an application might want to prevent getting it's focus stolen by using some API call which I don't remember right now.
A probably good solution would be to find all window handles currently from that user and then use each of these handles to use win32gui.ShowWindow(handle, command) to minimize it.
Although for this particular problem setting the locktimeout setting was enough.
If anyone wonders how I managed to launch an application to a desktop from a service, here is a link to the code.
Have you tried launching another processes than your own from the service to see if it gets focus? Like notepad and see if it steals focus from your browser? If so perhaps its the program that can take back the focus when it starts.
I otherwise beilive it's the wShowWindow attribute from the STARTUPINFO struct the lpStartupInfo points to that should control it. You also need STARTF_USESHOWWINDOW in dwFlags to use nShowWindow. The values should be SW_SHOW i think, they are listed for the ShowWindow function if you want to try other.
For various very legitimated reasons, Microsoft would rather not see a service launching an app and stealing focus, however I found the following work around to still accomplish what I want.
The original intend is to have a kiosk like application hindered by a pass code like splash screen, which upon entering a 8 character code closes the splash screen for a period time as in the pass code defined. Originally the actual application to use was started by the autostart folder.
However I now rewrote it that it is launched from my service, this way I can hide the application by launching an helper application from the service that just hides the program and launches the splash screen, upon exiting the splash screen the program is returned to the previous state.
How can I tell when Windows is changing a monitors power state?
It seems that, when Windows wants to start the screen saver or turn the monitor off, it will send a WM_SYSCOMMAND to the topmost window with a wParam of SC_SCREENSAVE (to start the screen saver) or a wParam of SC_MONITORPOWER and a lParam of 1 or 2 (to turn the monitor off). This message will then be passed to DefWindowProc, which will actually do the action. So, if your window happens to be the topmost one, you can intercept these events and ignore them (or do anything else you want before passing them to DefWindowProc).
On Windows Vista, there seems to be a more intuitive, and more reliable, way to know the monitor power state. You call RegisterPowerSettingNotification to tell the system to send your window a WM_POWERBROADCAST message with a wParam of PBT_POWERSETTINGCHANGE and a lParam pointing to a POWERBROADCAST_SETTING structure.
I cannot test either of them since I currently do not have any computer with Windows nearby. I hope, however, they point you in the right direction.
References:
The Old New Thing : Fumbling around in the dark and stumbling across the wrong solution
Recursive hook ... - borland.public.delphi.nativeapi.win32 | Google Groups
Registering for Power Events (Windows)