Awesome WM - Chatty (Java application) bypass dimension properties from rc.lua - linux

Chatty is a java application to chat in Twitch (streaming platform) from the desktop.
What I'm trying to accomplish is that Chatty always starts with specifics X, Y, width and height properties.
{ rule = { class = "chatty-Chatty" },
properties = {
width = 267,
height = 223,
x = 1575,
y = 774
},
},
The X and Y properties work just fine, wherever I move the window if I closed and open it again it appears in my desired position. However for some reason I fail to acknowledge Chatty doesn't care about the width and height properties, it always opens with the last geometry.
Chatty itself have a config file but there isn't anything related to width and height dimensions.
I'm on Arch, and the only WM I have is Awesome.
PD: One weird thing is that every time I'm changing the window size it also moves, always in a bottom right direction. This is annoying but not a problem, I'm mentioning this just in case it is related to the possible issue.

This is probably because they client resize itself after the rules are executed (which would be a bug in your app or Java). In any case, you can do:
client.disconnect_signal("request::geometry", awful.ewmh.client_geometry_requests)
to turn off the client ability to resize themselves.
In AwesomeWM git-master version, you can use the permission API to deny the "client" -> "geometry" -> "ewmh" permission per client.

Related

Resize Wry WebView from window.resizeTo

I have a web application currently running in Electron and would like to move it to Wry/Tauri for opening speed.
The application uses window.resizeTo to change the window size in real time.
I have tried using the same command with Wry/Tauri, but it does not work.
Is it possible to intercept such a call and act correctly?
Maybe will be useful for someone other. I figured out that it is possible to use webview.evaluate_script('<js code>') to inject some code in opened page.
Thus it's possible to change the default window.resizeTo functionallity to something I need to, for example for my needs I can do:
window.resizeTo = (w, h) => window.ipc.postMessage(`resize,${w},${h}`);
On the WRY side I can use with_ipc_handler to resize the window as requested.
WebViewBuilder::new()
.with_ipc_handler(|win, msg| {
let (w, h) = parse_resize_msg(&msg).unwrap();
win.set_inner_size(LogicalSize::new(w, h)).unwrap();
})
.build()?;

Why doesn't my Raycast2Ds detect walls from my tilemap

I am currently trying to make a small top-down RPG with grid movement.
To simplify things, when i need to make something move one way, I use a RayCast2D Node and see if it collides, to know if i can move said thing.
However, it does not seem to detect the walls ive placed until I am inside of them.
Ive already checked for collision layers, etc and they seem to be set up correctly.
What have i done wrong ?
More info below :
Heres the code for the raycast check :
func is_path_obstructed_by_obstacle(x,y):
$Environment_Raycast.set_cast_to(Vector2(GameVariables.case_width * x * rayrange, GameVariables.case_height * y * rayrange))
return $Environment_Raycast.is_colliding()
My walls are from a TileMap, with collisions set up. Everything that uses collisions is on the default layer for now
Also heres the function that makes my character move :
func move():
var direction_vec = Vector2(0,0)
if Input.is_action_just_pressed("ui_right"):
direction_vec = Vector2(1,0)
if Input.is_action_just_pressed("ui_left"):
direction_vec = Vector2(-1,0)
if Input.is_action_just_pressed("ui_up"):
direction_vec = Vector2(0,-1)
if Input.is_action_just_pressed("ui_down"):
direction_vec = Vector2(0,1)
if not is_path_obstructed(direction_vec.x, direction_vec.y):
position += Vector2(GameVariables.case_width * direction_vec.x, GameVariables.case_height * direction_vec.y)
grid_position += direction_vec
return
With ray casts always make sure it is enabled.
Just in case, I'll also mention that the ray cast cast_to is in the ray cast local coordinates.
Of course collision layers apply, and the ray cast has exclude_parent enabled by default, but I doubt that is the problem.
Finally, remember that the ray cast updates on the physics frame, so if you are using it from _process it might be giving you outdated results. You can call call force_update_transform and force_raycast_update on it to solve it. Which is also what you would do if you need to move it and check multiple times on the same frame.
For debugging, you can turn on collision shapes in the debug menu, which will allow you to see them when running the game, and see if the ray cast is positioned correctly. If the ray cast is not enabled it will not appear. Also, by default, they will turn red when they collide something.

How to apply shaders and generate images only once?

I'm trying to apply a pixelation shader to my textures and I need it to be applied only once, after that I can reuse my shader generated images as textures over and over without having to calculate every single time.
so how do I take a few images -> apply a shader and render them only once every time the game loads -> and use them as my textures?
so far I've managed to find the shader to apply:
shader_type canvas_item;
uniform int amount = 40;
void fragment()
{
vec2 grid_uv = round(UV * float(amount)) / float(amount);
vec4 text = texture(TEXTURE, grid_uv);
COLOR = text;
}
but I have no idea how to render out the images using it
Shaders reside in the GPU, and their output goes to the screen. To save the image, the CPU would have to see the GPU output, and that does not happen… Usually. And since it does not go through the CPU, the performance is good. Usually. Well, at least it is better than if the CPU was doing it all the time.
Also, are you sure you don't want to get a pixel art look by other means? Such as removing filter from the texture, changing the stretch mode and working on a small resolution, and perhaps enable pixel snap? No? Watch How to make a silky smooth camera for pixelart games in Godot. Still No? Ok...
Anyway, for what you want, you are going to need a Viewport.
Viewport setup
What you will need is to create a Viewport. Don't forget to set its size. Also may want to set render_target_v_flip to true, this flips the image vertically. If you find the output image is upside down it is because you need to toggle render_target_v_flip.
Then place as child of the Viewport what you want to render.
Rendering
Next, you can read the texture form the Viewport, convert it to an image, and save it to a png. I'm doing this on a tool script attached to the Viewport, so I'll have a workaround to trigger the code from the inspector panel. My code looks like this:
tool
extends Viewport
export var save:bool setget do_save
func do_save(new_value) -> void:
var image := get_texture().get_data()
var error := image.save_png("res://output.png")
if error != OK:
push_error("failed to save output image.")
You can, of course, export a FILE path String to ease changing it in the inspector panel. Here I'm handing common edge cases:
tool
extends Viewport
export(String, FILE) var path:String
export var save:bool setget do_save
func do_save(_new_value) -> void:
var target_path := path.strip_edges()
var folder := target_path.get_base_dir()
var file_name := target_path.get_file()
var extension := target_path.get_extension()
if file_name == "":
push_error("empty file name.")
return
if not (Directory.new()).dir_exists(folder):
push_error("output folder does not exist.")
return
if extension != "png":
target_path += "png" if target_path.ends_with(".") else ".png"
var image := get_texture().get_data()
var error := image.save_png(target_path)
if error != OK:
push_error("failed to save output image.")
return
print("image saved to ", target_path)
Another option is to use ResourceSaver:
tool
extends Viewport
export var save:bool setget do_save
func do_save(new_value) -> void:
var image := get_texture().get_data()
var error := ResourceSaver.save("res://image.res", image)
if error != OK:
push_error("failed to save output image.")
This will only work from the Godot editor, and will only work for Godot, since you get a Godot resource file. Although I find interesting the idea of using Godot to generate images. I'm going to suggest going with ResourceSaver if you want to automate generating them for Godot.
About saving resources from tool scripts
In the examples above, I'm assuming you are saving to a resource path. This is because the intention is to use the output image as a resource in Godot. Using a resource path has a couple implications:
This might not work on an exported game (since the goals is improve the workflow, this is OK).
Godot would need to re-import the resource, but will not notice it changed.
We can deal with the second point from an EditorPlugin, if that is what you are doing, you can do this to tell Godot to scan for changes:
get_editor_interface().get_resource_filesystem().scan()
And if you are not, you can cheat by creating an empty EditorPlugin. The idea is to do this:
var ep = EditorPlugin.new()
ep.get_editor_interface().get_resource_filesystem().scan()
ep.free()
By the way, you will want to cache cache the EditorPlugin instead of making a new one each time. Or better yet, cache the EditorFileSystem you get from get_resource_filesystem.
Automation
Now, I'm aware that it can be cumbersome to have to place things inside the Viewport. It might be Ok for your workflow if you don't need to do it all the time.
But what about automating it? Well, regardless of the approach, you will need a tool script that makes a hidden Viewport, takes a Node, checks if it has a shader, if it does, it moves it temporarily to the Viewport, get the rendered texture (get_texture()) sets it as the texture of the Node, removes the shader, and returns the Node to its original position in the scene. Or instead of looking for a shader in the Node, always apply a shader to whatever Node, perhaps loaded as a resource instead of hard-coded.
Note: I believe you need to let an idle frame pass between adding the Node to the Viewport and getting the texture, so the texture updates. Or was it two idle frames? Well, if one does not work, try adding another one.
About making an EditorPlugin
As you know, you can create an addon from project settings. This will create an EditorPlugin script for you. There you can either add an option to the tools menu (with add_tool_menu_item), or add it to the tool bar of the editor (with add_control_to_container). And have it act on the current selection in the edited scene (you can either use get_selection, or overwrite the edit and handles methods). You may also want to make an undo entry for that, see get_undo_redo.
Or, alternatively you can have it keep track (or look for) the Nodes it has to act upon, and then work on the build virtual method, which runs when the project is about to run. I haven't worked with the build virtual method, so I don't know if it has any quirks to gotchas to be aware of.

X11 FocusIn is not working

As long as I understand it, the X11 FocusIn event is triggered whenever the window comes into focused. It the the window that the keyboard input is sent to. I am having trouble triggering this event. I have made sure to give it the FocusChangeMask when creating the window. I have created a breakpoint inside my event handler where the FocusIn event is supposed to happen and it is not stopping.
I have 2 separate window, a transparent one and one non-transparent. Currently I have it so the transparent window is always on top of the non transparent window. Whenever I switch focus and then switch back to the transparent window, the non-transparent window is directly underneath. This causes other windows to be stuck in 'between' the transparent and non-transparent window.
I have noticed that whenever I focus on the non-transparent window that is underneath that triggers the FocusIn event. I can not get the transparent window to trigger the event. Does this have something to do with the window being in 32-bit color?
What am I missing?
while(!renderer->stop)
{
XNextEvent(renderer->x_display, &event);
switch(event.type)
{
case Expose:
if (event.xexpose.window == gstreamer_window)
{
XRaiseWindow(renderer->x_display, renderer->opengl_window);
}
break;
case FocusIn:
if (event.xfocus.window == renderer->opengl_window)
{
XRaiseWindow(renderer->x_display, gstreamer_window);
}
break;
case ConfigureNotify:
if (event.xconfigure.window == renderer->opengl_window)
{
XMoveWindow(renderer->x_display, gstreamer_window,
event.xconfigure.x, event.xconfigure.y - top_border_offset);
}
break;
}
}
Here is how I created the window.
XSetWindowAttributes swa;
swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask | FocusChangeMask;
swa.colormap = XCreateColormap(x_display, XDefaultRootWindow(x_display), visual, AllocNone);
swa.background_pixel = 0;
swa.border_pixel = 0;
/* Create a window */
opengl_window = XCreateWindow (
x_display, parent,
0, 0, m_plane_width, m_plane_height, 0,
depth, InputOutput,
visual, CWEventMask | CWBackPixel | CWColormap | CWBorderPixel,
&swa );
It appears as though I set the FocusChangeMask at the wrong place. By adding the line XSelectInput(x_display, opengl_window, FocusChangeMask)
, it now triggers the FocusIn event. It was triggering the other display because it had the mask but this one didn't.
It's not clear from your question whether the windows referenced in your question are top level application windows, or secondary, ancillary windows that are child windows of your top level application windows.
But in all cases, proper input focus handling requires you to inform the window manager exactly how your application expects to handle input focus.
See section 4.1.7 of the ICCCM specification for more information. Unfortunately, it's not enough just to code an event loop that handles FocusIn messages, and expect them to fall out of the sky. First, you need to tell your window manager how exactly you are going to handle input focus switching, then respond to the window manager's messages, as explained in the ICCCM specification; perhaps by explicitly sending the SetInputFocus requests for your own application windows.
See my post under OP's self accepted answer for background
I had the same problem and it seems if you use XSelectInput it overrides the event mask for a window, instead of adding to it. You need to either:
skip adding XSelectInput and set the event masks on the window when created
or add all of the masks for the window to the XSelectInput command
Here's my similar setup which worked before I added the XSelectInput line:
swa.event_mask = StructureNotifyMask | SubstructureNotifyMask | FocusChangeMask | ExposureMask | KeyPressMask;
wnd = XCreateWindow(disp, wndRoot, left, top, width, height, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa);
XMapWindow(disp, wnd);
When I added this for capturing key input:
XSelectInput(disp, wnd, KeyPressMask | KeyReleaseMask);
everything else stopped working, which I didn't realize for a while, until now, because I was just testing keys.
I have a single window application with no controls in the client area, so I don't know what else XSelectInput does for a window that already has the masks, but I do get key up and down messages without it. In the OP's self accepted answer he just goes the other way and adds 'FocusChangeMask' to XSelectInput instead.
The documentation for a lot of X11 is, in my opinion, a lot like the standard Apple documentation where it has the affliction of never saying what the function really actually does or affects, but tells you all about everything else. (See bottom snippet here) To be fair a good portion of the Cocoa docs are pretty decent, but maybe half are not. That goes for many or most of the parameters as well.
From Linux man page which I think is the maybe verbatim the same as the Xlib manual here https://tronche.com/gui/x/xlib/
The XSelectInput function requests that the X server report the events associated with the specified event mask.
Setting the event-mask attribute of a window overrides any previous call for the same window but not for other clients.
(Below is my own perhaps incorrect rewording of the XInputSelect docs)
This can be interpreted as perhaps:
XSelectInput sets the event-mask on a window for a display for events reported to the client. Each client can set its own independent mask for events it wants to receive with the following exceptions (skipping the exceptions).
Now the critical part:
XInputSelect will override and replace for a client any previous event-mask settings for a window on a display, including any event-mask set when creating the window.
And what I wish it was written as to make sure its understood, if true, that the XInputSelect does nothing else like enable key to character interpretation and what not, because I believe the core confusion is that people from all the various examples out there get the impression that there is some other magic besides setting mask. I'm assuming there's not, and the docs speak of no other magic besides the mask.
XInputSelect sets the event-mask for a window and allows for setting an event mask after a window is created.
And my opinion is that that line should have been first.

FMOD surround sound openframeworks

Ok, I hope I don't mess this up, I have had a look for some answers but can't find anything. I am trying to make a simple sampler in openframeworks using the FMOD sound player in 3D mode. I can make a single instance work fine (recording a new file using libsndfilerecorder and then playing it back and moving it in surround.
However I want to have 8 layers of looping audio that I can record and replace one layer at a time in a live show. I get a lot of problems as soon as I have more than 1 layer.
The first part of my question relates to the FMOD 3D modes, it is listener relative, so I have to define the position of my listener for every sound (I would prefer to have head relative mode but I cannot make this work at all. Again this works fine when I am using a single player but with multiple players only the last listener I update actually works.
The main problem I have is that when I use multiple players I get distortion, and often a mix of other currently playing sounds (even when the microphone cannot hear them) in my new recordings. Is there an incompatability with libsndfilerecorder and FMOD?
Here I initialise the players
for (int i=0; i<CHANNEL_COUNT; i++) {
lvelocity[i].set(1, 1, 1);
lup[i].set(0, 1, 0);
lforward[i].set(0, 0, 1);
lposition[i].set(0, 0, 0);
sposition[i].set(3, 3, 2);
svelocity[i].set(1, 1, 1);
//player[1].initializeFmod();
//player[i].loadSound( "1.wav" );
player[i].setVolume(0.75);
player[i].setMultiPlay(true);
player[i].play();
setupHold[i]==false;
recording[i]=false;
channelHasFile[i]=false;
settingOsc[i]=false;
}
When I am recording I unload the file and make sure the positions of the player that is not loaded are not updating.
void fmodApp::recordingStart( int recordingId ){
if (recording[recordingId]==false) {
setupHold[recordingId]=true; //this stops the position updating
cout<<"Start recording Channel " + ofToString(recordingId+1)+" setup hold is true \n";
pt=getDateName() +".wav";
player[recordingId].stop();
player[recordingId].unloadSound();
audioRecorder.setup(pt);
audioRecorder.setFormat(SF_FORMAT_WAV | SF_FORMAT_PCM_16);
recording[recordingId]=true; //this starts the libSndFIleRecorder
}
else {
cout<<"Channel" + ofToString(recordingId+1)+" is already recording \n";
}
}
And I stop the recording like this.
void fmodApp::recordingEnd( int recordingId ){
if (recording[recordingId]=true) {
recording[recordingId]=false;
cout<<"Stop recording" + ofToString(recordingId+1)+" \n";
audioRecorder.finalize();
audioRecorder.close();
player[recordingId].loadSound(pt);
setupHold[recordingId]=false;
channelHasFile[recordingId]=true;
cout<< "File recorded channel " + ofToString(recordingId+1) + " file is called " + pt + "\n";
}
else {
cout << "Sorry track" + ofToString(recordingId+1) + "is not recording";
}
}
I am careful not to interrupt the updating process but I cannot see where I am going wrong.
Many Thanks
to deal with the distortion, i think you will need to lower the volume of each channel on playback, try setting the volume to 1/8 of the max volume. there isn't any clipping going on so if the sum of sounds > 1.0f you will clip and it will sound bad.
to deal with crosstalk when recording: i guess you have some sort of feedback going on with the output, ie the output sound is being fed back into the input channel, probably by the operating system. if you run another app that makes sound do you also get that in your recording as well? if so then that is probably your problem.
if it works with one channel, try it with just 2, instead of jumping straight up to 8 channels.
in general i would try to abstract out the playback/record logic and soundPlayer/recorder into a separate class. you have a couple of booleans there and it's really easy to make mistakes with >1 boolean. is there any way you can replace the booleans with an enum or an integer state variable?
EDIT: I didn't see the date on your question :D Suppose you managed to do it by now. Maybe it helps somebody else..
I'm not sure if I can answer everything of your question, but I can share how I've worked with 3D sound in FMOD. I haven't worked with recording though.
For my own application a user can place sounds in 3D space around himself. For this I only have one Listener and multiple Sounds. In your code you're making a listener for every sound, are you sure that is necessary? I would imagine that this causes the multiple listeners to pick up multiple sounds and output that to your soundcard. So from the second sound+listener, both listeners pick up both sounds? I'm not a 100% sure but it sounds plausible to me.
I made a class to create sound objects (and one listener). Then I use a vector to store the objects and move trough them to render them.
My class SoundBox basically holds all the necessary things for FMOD
Making a "SoundBox" object and adding it to my soundboxes vector:
SoundBox * box = new SoundBox(box_loc, box_rotation, box_color);
box->loadVideo(ofToDataPath(video_files[soundboxes.size()]));
box->loadSound(ofToDataPath(sound_files[soundboxes.size()]));
box->setVolume(1);
box->setMultiPlay(true);
box->updateSound(box_loc, box_vel);"
box->play();
soundboxes.push_back(box);
Constructor for the SoundBox. I use a similar constructor in the same class for the listener, but since the listener will always be at the origin for me, it doesn't take any arguments and just sets all the listener locations to 0. The constructor for the listener only gets called once, while the one for the Sound gets called whenever I want to make a new one. (don't mind the box_color. I'm drawing physical boxes in this case..):
SoundBox::SoundBox(ofVec3f box_location, ofVec3f box_rotation, ofColor box_color) {
_box_location = box_location;
_box_rotation = box_rotation;
_box_color = box_color;
sound_position.x = _box_location.x;
sound_position.y = _box_location.y;
sound_position.z = _box_location.z;
sound_velocity.x = 0;
sound_velocity.y = 0;
sound_velocity.z = 0;
Then I just use a for loop to loop trough them and play them if they're not playing. I also have some similar code to select them and move then around.
for(auto box = soundboxes.begin(); box != soundboxes.end(); box++){
if(!(*box)->getIsPlaying())
(*box)->play();
}
I really hoped this helped. I'm not a very experienced programmer but this is how I got FMOD with multiple sounds to work in OpenFrameworks and hope you can use some of it. I just dumped as much of my code as I could :D
My main suggestion is to make one listener instead of more. Also having a class for making the sounds is useful if you, for instance, want to relocate the sounds after the initial placement.
Hope it helps and good luck :)

Resources