I have a C++ program that I used this simple gtk code at first of my main() function, and my goal is my app shows an image when it started and keeping showing the image and keep the rest of program.
GtkWidget* window;
GtkWidget* image1;
GtkWidget* image2;
gtk_init (NULL,NULL);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
image1 = gtk_image_new_from_file("1.jpg");
image2 = gtk_image_new_from_file("2.jpg");
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(G_OBJECT (window), "destroy",
G_CALLBACK (destroy), NULL);
gtk_container_add(GTK_CONTAINER (window), image1);
gtk_widget_show_all(window);
gtk_main();
THE REST OF PROGRAM THAT WONT EXECUTE!
But when it opens a window and shows the image, it stuck there and doesn't execute the rest of code! Why this happens?
After you execute gtk_main, your code will "block", if i can say that, in that line until gtk_main_quit it's called/executed.
This is the nature of graphical user interfaces. Typically, you setup everything, call the main loop and wait for user interaction.
I would suggest that you read GNOME's Getting Started with GTK+.
As an example, if you do any printf below gtk_main, it will get printed after you close the GtkWindow.
Your application logic must be defined previously, then by means of user interaction, pressing buttons and other widgets, the application will do "things".
When you call gtk_main, the main loop starts.
The main event loop manages all the available sources of events for
GLib and GTK+ applications. These events can come from any number of
different types of sources such as file descriptors (plain files,
pipes or sockets) and timeouts.
You can read more about it here.
Related
Question
How to use these private functions on other windows? It would be nice to have this knowledge back in the wild. I am specifically trying to get CGSOrderWindow and CGSSetWindowLevel to work.
I was trying in the direction of:
temporarily register as the dock and then register the dock as the dock again immediately afterwards
or
code injection into the Dock process per this comment:
Also, the author of the above project seems determined to make all core functionality available as a framework. It seems to be implemented as code injection into the Dock process.
Reason I know this is possible
I have been doing work on trying to setLevel on window of another app, and focus window of another app if focused. I am posting this again with the info I learned because from my searching online, I know this was done in the past, its just the knowledge is not publicly out there anymore. The sourceforge pages are no longer there. So I was wondering if you could help me make this information public again.
This is the topic I read that gave me this information - http://cocoadev.com/HowtoControlOtherAppsWindows
Here you see comments like:
You cannot control an another app's windows from a user-level process, unfortunately.
SlavaKarpenko
You can, Slava, you just need to register as the Dock. It might be possible to temporarily register as the dock and then register the dock as the dock again immediately afterwards, not sure. I think the call you'd be wanting to investigate as CoreDockRegisterDockOwner in HIServices.framework.
FinlayDobbie
You could also use APE or similar to do control the windows, or (as mentioned above) register as the Dock (look for the private APIs with Universal Connection in their name). Has anyone found a polite way of getting the Dock to give up its universal connection? The only way I can find is to force quit the Dock and grab the universal connection when it's not looking (which prevents the dock reloading).
SamTaylor
There's an open source project up on sourceforge.net that looks much more like the window managers I've used on Unix boxes than Space.app (or Space.dock): http://wsmanager.sourceforge.net/
SteveCook
Verifying things work
This is what I learned, from the sources at bottom of this post, we see all these functions work with CGWindowIds, so how do I get that, this is how:
Get all windows with CGWindowListCopyWindowInfo. Then access each element from that array with CFArrayGetValueAtIndex and then get the CGWindowId with objectForKey:, kCGWindowNumber, and then integerValue.
Now if I try to focus or set level of a window that is OWNED by the app running the code, it works fantastic. For instance:
MY_TARGET_CGWINDOW_ID = 179;
rez_CGError = CGSOrderWindow(_CGSDefaultConnection, MY_TARGET_CGWINDOW_ID, kCGSOrderAbove, 0);
Will focus it, rez_CGError is 0. Even if the window is minimized, it is unminimized, without animation, and shown.
Now however, if I try this on a window of a different app we get some errors:
MY_TARGET_CGWINDOW_ID_of_other_app = 40;
rez_CGError = CGSOrderWindow(_CGSDefaultConnection, MY_TARGET_CGWINDOW_ID_of_other_app, kCGSOrderAbove, 0);
This fails and rez_CGError is 1000, which I suspect means "cid (CGSConnection) used does not have permission to modify target window". The same happens if I first do [app activateWithOptions: (NSApplicationActivateIgnoringOtherApps | NSApplicationActivateAllWindows)] before making the call above.
So I first get the cid of that owning window like this:
var rez_CGError = CGSGetWindowOwner(_CGSDefaultConnection, MY_TARGET_CGWINDOW_ID_of_other_app, &ownerCid);
This works good and I get ownerCid is set to a value. Then I do the focus command with this new connection:
rez_CGError = CGSOrderWindow(ownerCid, MY_TARGET_CGWINDOW_ID_of_other_app, kCGSOrderAbove, 0);
However this gives rez_CGError of 268435459, which I suspect means "current app does not have permission to use this ConnectionId (cid)". (Same happens if I call activateWithOptions first.
My Sources for the Private Functions
Here is the sources for some private functions I found - https://code.google.com/p/undocumented-goodness/source/browse/trunk/CoreGraphics/CGSPrivate.h
This one source here contains a function that is not in the above link - CGSGetConnectionIDForPSN - i test it and it exists - from - https://github.com/mnutt/libqxt/blob/767498816dfa1742a6f3aee787281745afec11b8/src/gui/qxtwindowsystem_mac.h#L80
I have made a custom virtual keyboard widget for my kiosk application, and now comes the time when I want it to produce fake keyboard events and feed them to an QLineEdit of choice.
I do the following:
// target is the QWidget to receive the events
// k is the Qt::Key (keycode) I want to send (Testing with an 'A')
Qt::Key k=Qt::Key_A;
if(0!=target){
//According to docs this will be freed once posted
QKeyEvent * press=new QKeyEvent(QKeyEvent::KeyPress, (int )k,0);
QKeyEvent * release=new QKeyEvent(QKeyEvent::KeyRelease, (int )k,0);
//Give the target focus just to be sure it is available for input
target->setFocus();
//Post the events (queue up and let the target consume them when the eventloop gets around to the target)
QCoreApplication::postEvent ( target, press) ;
QCoreApplication::postEvent ( target, release) ;
}
I see the target widget receive focus, but there are no letters typed into the input field like I would expect. What am I doing wrong? Which assumptions are wrong?
PS: I know that this could be solved by using existing virtual keyboards or at least using the platform interface as is done in this post. In our approach we have decided to build the kayboard into the application to obtain full control over the UX and keyboard design.
Thanks!
Since no-one stepped up, I will try to provide some closure.
It turns out that Qt5 comes with a library of testing facilities called testlib. It has all sorts of goodies to facilitate easy creation, management and running of unit tests for Qt application. Among these facilities there is a set of functions for sending fake events such as fake typing of text, mouse clicks etc. It is quite comprehensive and covers many use-cases. Since this is used internally by Qt developers to test Qt itself it is also production proven code.
I simply copied what I needed from there.
I am trying to integrate GTK (in a .NET application via the gtk-sharp bindings) into an application that already has a "main loop." Calling Gtk.Application.Run() results in the entire thing basically locking up while waiting on the Gtk loop. Furthermore, this app can't really be integrated into GTK in the usual sense (that is, using GTK's idle stuff to pump the app for events).
Is there a way to do the opposite and run the GTK main event loop manually?
Right now I have something like this:
def _pump_gtk():
while true:
if Gtk.Application.EventsPending():
Gtk.Application.RunIteration()
yield
(the yield is because _pump_gtk is running as a coroutine in the main application)
However, this seems to have problems because Gtk doesn't think there is a main loop running? I get a lot of Gtk-CRITICAL **: gtk_main_quit: assertion main_loops != NULL' failed errors.
Is there a way to run the GTK main loop manually?
I made a game have two objects in the hierarchy panel. One called GameScreen and another called Clock I set up. Each has its own script attached. GameScreen uses game.js and the other uses clock.js.
When I win the game a popup box appears and says, "You've won!" This is caused by the game.js script. However, the clock.js is still running, so my clock is still counting down. When the time is up the clock.js makes a popup box saying, "you lose!"
This causes for a "you win" screen to pop up when you win and then later a you lose screen to appear. As you can probably guess, this is super annoying. If there was a way I could change variables in one script from another,, I could get the clock to stop when you won or I could get the game to stop when the time ran out.
Is there some way to do this??
For example here are two javascript files one on clock and the other on GameScreen . I want the first one to change the variable changeMe in the second to two.
1.js:
function start(){
}
2.js:
var changeMe:int;
When you win the game, you can change clock's variable from game.js this way:
GameObject.Find("Clock").GetComponent("clock.js").variable_name = new_value;
, where [variable_name] and [new_value] obviously depend on your project. variable_name has to be an exposed variable.
You can simply use SendMessage() it will make you able to call a function from another object easily.Basically you need to write a function to destroy the clock after wining the game,let's say your function is called destroyClock so you should add that to your game.js script:
gameobject.Find("here goes the name of your clock obj").sendMessage("destroyClock")
So I have been pulling my hair out all day at this, and I am out of patience.
Basically I have a pygtk program that is built from glade. At the bottom of the main window, there is a status bar that I use to display usage errors, and status messages about the connected hardware and they use the functions below. So all of the calls to displayError come from within my object based on user interaction, and they all seem to work. In testing I tried making calls to displayCurrent and it works as well. The problem comes when the hardware process tries to use displayCurrent. The way the system works is that one of the members of my main window class is an interface object to the hardware. This has a separate process, using multiprocessing.Process, which sends a signal every time it gets data with the data being the message to output. Does anyone have any ideas? I'll be happy to explain anything in more depth if needed, it's just a LOT of code to post to get all the details.
def displayCurrent(self, message):
print message
if self.lastMess:
self.statusBar.remove(self.normalID, self.lastMess)
self.lastMess = self.statusBar.push(self.normalID, message)
def displayError(self, message, timeout = 5):
"""
Function that takes an error message and raises it to the user via the statusbar
timeout seconds later.
"""
print message
mess = self.statusBar.push(self.urgentID, message)
# clear statusbar
gobject.timeout_add_seconds(timeout, self.clearStatus, self.urgentID, mess)
def clearStatus(self, cID, mID):
#time.sleep(timeout)
self.statusBar.remove(cID, mID)
#print self.statusBar.remove_all(self.urgentID)
print 'popped'
return False
Post the whole code.
In general, this won't work if you are in a separate process. GTK (and everything else) has been forked. You need to use some form of interprocess communication. Multiprocessing module handles it for you. There are also hacks you can do in GTK such as using a window title (like Vim) or perhaps a plug and socket to communicate; don't be tempted by these.