I am writing a GTK application to display a system tray icon and capture user inputs from keyboard. I have written an inifinite loop to capture user inputs. But how to make it work with gtk main loop? Thanks in advance for any idea.
My try:-
use device_query::{DeviceQuery, DeviceState, Keycode};
let device_state = DeviceState::new();
let mut started = false;
loop {
let keys: Vec<Keycode> = device_state.get_keys();
match keys.last() {
Some(key)=>{
match key {
Keycode::LControl=>{
started = true;
}
Keycode::RControl=>{
started = true;
}
Keycode::F6=>{
if started {
println!("Fired");
}
started = false;
}
_=>{
started = false;
}
}
}
None=>{}
}
}
gtk::main();
Related
I added collision between the player and the ground, and I want to add a jumping mechanic into my game with on_ground. However, whenever I try to add status, it just stops iterating entirely.
fn collision_detection(
ground: Query<&Transform, (With<Ground>, Without<Player>)>,
mut player: Query<(&mut Transform, &mut PlayerStatus), With<Player>>,
) {
let player_size = Vec2::new(PLAYER_SIZE_X, PLAYER_SIZE_Y);
let ground_size = Vec2::new(GROUND_SIZE_X, GROUND_SIZE_Y);
for ground in ground.iter() {
for (mut player, mut status) in player.iter_mut() {
if collide(
player.translation,
player_size,
ground.translation,
ground_size,
)
.is_some()
{
status.on_ground = true;
println!("ON GROUND")
} else {
status.on_ground = false;
}
if status.on_ground {
player.translation.y += GRAVITY;
}
}
}
}
For some reason, this part wouldn't run
for (mut player, mut status) in player.iter_mut() {
if collide(
player.translation,
player_size,
ground.translation,
ground_size,
)
.is_some()
{
status.on_ground = true;
println!("ON GROUND")
} else {
status.on_ground = false;
}
if status.on_ground {
player.translation.y += GRAVITY;
}
}
It works if I only do this though:
for mut player in player.iter_mut() {
if collide(
player.translation,
player_size,
ground.translation,
ground_size,
)
.is_some()
{
player.translation.y += GRAVITY;
}
}
If you have only one player, you can use get_single_mut() instead of iter_mut() on the query.
It returns a result, so you can check in your function easily whether the player entity had been found at all. And if not send yourself some nice debugging message :)
if let Ok((mut player, mut status)) = player.get_single_mut() {
// do your collision check
} else {
// player not found in the query
}
https://docs.rs/bevy/latest/bevy/prelude/struct.Query.html#method.get_single_mut
Edit:
Looking at your comment above: if you have an already spawn entity you can always add new components to it using .insert_bundle or .insert.
I've created a custom GJS extension to connect into VPN. Basically it's a wrapper around a shell script, which is controlled from taskbar. There is a one issue, that after PC goes into suspend mode and back, extension is still displaying, that is disconnected, while it's still connected.
const GObject = imports.gi.GObject;
const St = imports.gi.St;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Gettext = imports.gettext;
const _ = Gettext.gettext;
const Me = imports.misc.extensionUtils.getCurrentExtension();
const MainLoop = imports.mainloop;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
let close_connection = `
pkexec kill -SIGINT $(pidof openconnect) 2>&1
`;
let create_connection = `
trap clean SIGINT
clean() {
pkexec kill -SIGINT $(pidof openconnect) 2>&1
}
vpn-ura-pke &
wait
`;
let _icon;
let _connectionSwitch;
let _last_connection = false;
let _already_running = false;
let _proc = null;
const iconsState = [
'network-vpn-acquiring-symbolic', // disconnected
'network-vpn-symbolic' // connected
];
function setConnectionState(connected) {
// prevent same notification changing
if (_last_connection == connected) return;
_icon.icon_name = iconsState[connected ? 1 : 0];
Main.notify('VPN URA', (connected ? 'connected' : 'disconnected'));
_last_connection = connected;
}
// read line callback
function onProcLine(stream, result) {
try {
let line = stream.read_line_finish_utf8(result)[0];
if (line !== null) {
// process read line
log("onProcLine:" + line);
// check connection status
if (line.includes('Connected as ')) setConnectionState(true);
else if(line.includes('Logout successful')) setConnectionState(false);
stream.read_line_async(0, null, onProcLine.bind(this));
}
} catch (ex) {
logError(ex);
}
}
// exec async process
async function execCheck(argv) {
_proc = new Gio.Subprocess({
argv: argv,
flags: (Gio.SubprocessFlags.STDIN_PIPE |
Gio.SubprocessFlags.STDOUT_PIPE |
Gio.SubprocessFlags.STDERR_PIPE)
});
_proc.init(null);
try {
let stdoutStream = new Gio.DataInputStream({
base_stream: _proc.get_stdout_pipe()
});
stdoutStream.read_line_async(
GLib.PRIORITY_DEFAULT,
null,
onProcLine.bind(this)
);
_proc.wait_check_async(null, (_proc, res) => {
try {
if (!_proc.wait_check_finish(res)) {
let status = _proc.get_exit_status();
setConnectionState(false);
if (status != 0) {
throw new Gio.IOErrorEnum({
code: Gio.io_error_from_errno(status),
message: GLib.strerror(status)
});
}
}
} catch (ex) {
setConnectionState(false);
logError(ex);
} finally {
_connectionSwitch.setToggleState(false);
}
});
} catch (ex) {
logError(ex);
}
}
const Indicator = GObject.registerClass(
class Indicator extends PanelMenu.Button {
toggleConnection(enabled) {
if (enabled) {
log("enable connection");
// start process
execCheck([
'bash',
'-c',
create_connection]
);
} else {
log("disable conenction");
// close running process
if (_proc) _proc.send_signal(2);
else if (_already_running) {
// kill process
Gio.Subprocess.new([
'bash',
'-c',
close_connection],
Gio.SubprocessFlags.STDOUT_PIPE
);
_already_running = false;
setConnectionState(false);
}
}
}
_init() {
super._init(0.0, _('VPN URA'));
// set icon
_icon = new St.Icon({
icon_name: iconsState[0],
style_class: 'system-status-icon'
});
this.add_child(_icon);
// toggle connection
_connectionSwitch = new PopupMenu.PopupSwitchMenuItem('Connection', false);
_connectionSwitch.connect('toggled', (_item, state) => {
this.toggleConnection(state);
});
this.menu.addMenuItem(_connectionSwitch);
// check if process is not already running
let [, , , status] = GLib.spawn_command_line_sync('pidof openconnect');
if (status == 0) {
_already_running = true;
_connectionSwitch.setToggleState(true);
setConnectionState(true);
}
}
});
class Extension {
constructor(uuid) {
this._uuid = uuid;
}
enable() {
_already_running = false;
this._indicator = new Indicator();
Main.panel.addToStatusArea(this._uuid, this._indicator, 1);
}
disable() {
_proc = null;
_connectionSwitch = null;
_last_connection = false;
_icon.destroy();
_icon = null;
this._indicator.destroy();
this._indicator = null;
}
}
function init(meta) {
return new Extension(meta.uuid);
}
Even if I added a case, where I was trying to use pidof to detect if process is running already. It caught only the case, when process was started outside from extension, but not the case, which I wanted.
How to bind into callback, which is fired up when session is restored? Or is there any another way to handle this?
Thanks,
Andy
I do also attempt to write a basic gnome extension for the same purpose.
Being very new to gjs coding, I found those answers regarding connection updating, in my research.
Hope some of it might help you :
Util.spawnCommandLine does not work on GNOME Shell extension
How to get OS name while writing gnome-extensions
GLib run command with root privileges
Running an asynchronous function in a GNOME extension
I'm trying to make a borderless window that can be maximized and minimized, but I can't get any information on how to get the current state of the window (if it's minimized or maximized) and how to use it.
(edit) rough snippets of the code:
SDL_Rect minimize_area = {0,0,20,20};
Button minimize_window_button = Button(minimize_area);
SDL_Rect maximize_area = {0,0,20,20};
Button maximize_window_button = Button(maximize_area);
SDL_Rect close_area = {0,0,20,20};
Button close_window_button = Button(close_area);
// Program loop
while ( SDL_PollEvent( &event ) ) {
case SDL_MOUSEBUTTONDOWN:
if (event.button.button == SDL_BUTTON_LEFT) {
mouse.updateMousePosition();
if (close_window_button.mouseInDstRect(mouse.pos.x, mouse.pos.y)) running = false;
if (maximize_window_button.mouseInDstRect(mouse.pos.x, mouse.pos.y)) {
if (/* WAY TO KNOW IF THE WINDOW IS MAXIMIZED */) {
SDL_MaximizeWindow(window);
} else {
SDL_RestoreWindow(window);
}
}
if (minimize_window_button.mouseInDstRect(mouse.pos.x, mouse.pos.y)) {
if (/* WAY TO KNOW IF WINDOW IS MINIMIZED or UNMINIMIZED */) {
SDL_MinimizeWindow(window);
} else {
SDL_RestoreWindow(window);
}
}
}
SDL_Log("click!");
break;
}
SDL_GetWindowFlags(), check the SDL_WINDOW_MINIMIZED & SDL_WINDOW_MAXIMIZED bits.
Modify Realm Object from background thread cannot update on main thread immeditly
My code is like this:
class demo: NSObject {
var mail: OutMailModel?
func demotest() {
let realm = try! Realm()
let mailID = 10001
self.mail = realm.object(ofType: OutMailModel.self,forPrimaryKey: mailID)
DispatchQueue.global().async {
let realm = try! Realm()
if let myMail = realm.object(ofType: OutMailModel.self,forPrimaryKey: mailID) {
try! realm.write {
myMail.message = "xxxx"
}
}
DispatchQueue.main.async {
NSLog("mail.message:\(self.mail?.message)") // message not change
}
}
}
}
event this not work:
DispatchQueue.main.async {
let realm = try! Realm()
if let myMail = realm.object(ofType: OutMailModel.self,forPrimaryKey: mailID) {
NSLog("mail.message:\(myMail.message)") // message not changed
}
}
what's wrong is the code? Any one help?
When updating the realm from a background thread, the changes might not be visible because the realm isn't being updated with the new information. From the docs:
On the main UI thread (or any thread with a runloop) objects will
automatically update with changes from other threads between each
iteration of the runloop. At any other time you will be working on the
snapshot, so individual methods always see a consistent view and never
have to worry about what happens on other threads.
You can call realm.refresh() to force a refresh of the realm:
func demotest() {
...
DispatchQueue.global().async {
let realm = try! Realm()
if let myMail = realm.object(ofType: OutMailModel.self,forPrimaryKey: mailID) {
try! realm.write {
myMail.message = "xxxx"
}
}
realm.refresh();
DispatchQueue.main.async {
NSLog("mail.message:\(self.mail?.message)") // message not change
}
}
}
I have really big problems when i try to compile my PrepareForSegue function:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "findMap" {
let MapViewController = segue.destinationViewController as UIViewController
if sender as UITableView == self.searchDisplayController!.searchResultsTableView {
let indexPath = self.searchDisplayController!.searchResultsTableView.indexPathForSelectedRow()!
let destinationTitle = filteredDepartments[indexPath.row].name
MapViewController.title = destinationTitle
} else {
let indexPath = self.tableView.indexPathForSelectedRow()!
let destinationTitle = departments[indexPath.row].name
MapViewController.title = destinationTitle
}
}
}
The error opens in the Thread section in the "trap"-row:
--> 0x2f6e18: trap
and the error code is as above:
--> Thread 1: EXC_BREAKPOINT(code=EXC_ARM_BREAKPOINT, subcode=0xdefe
I think the error is in this line:
if sender as UITableView == self.searchDisplayController!.searchResultsTableView {
Bur i don't know how to solve it , so please help me ...
It's hard to tell what your code is supposed to mean, but my guess is that you mean this:
if sender === self.searchDisplayController!.searchResultsTableView {
Notice the use of the triple-equals operator to mean "is the same object as".