Can't reserve space for window with xcb - x11

I'm trying to create a status bar in rust using xcb. I have written one already in C++ already using a mix of xcb and xlib so I'll be using that as a point of comparison. I'm also testing this on openbox which is a window manager written in xlib if that matters.
I'm currently unable to reserve space for my bar in the rust version. Below is the full output of xprop
WM_CLASS(STRING) = "onyxbar"
WM_NAME(STRING) = "bar"
_NET_WM_STRUT(CARDINAL) = 0, 0, 20, 0
_NET_WM_STRUT_PARTIAL(CARDINAL) = 0, 0, 20, 0, 0, 0, 0, 0, 1920, 3840, 0, 0
_NET_WM_STATE(ATOM) = _NET_WM_STATE_STICKY, _NET_WM_STATE_ABOVE
_NET_WM_WINDOW_TYPE(CARDINAL) = _NET_WM_WINDOW_TYPE_DOCK
you can see that the relevant _NET_WM_STRUT and _NET_WM_STRUT_PARTIAL are the same between this and the xprop output for my working bar in c++:
WM_STATE(WM_STATE):
window state: Normal
icon window: 0x0
_NET_WM_ALLOWED_ACTIONS(ATOM) = _NET_WM_ACTION_CHANGE_DESKTOP, _NET_WM_ACTION_BELOW
_KDE_NET_WM_FRAME_STRUT(CARDINAL) = 0, 0, 0, 0
_NET_FRAME_EXTENTS(CARDINAL) = 0, 0, 0, 0
_NET_WM_ICON(CARDINAL) = Icon (48 x 48): (some big ascii icon)
_OB_APP_TYPE(UTF8_STRING) = "dock"
_OB_APP_TITLE(UTF8_STRING) = "bar"
_OB_APP_GROUP_CLASS(UTF8_STRING) =
_OB_APP_GROUP_NAME(UTF8_STRING) =
_OB_APP_CLASS(UTF8_STRING) =
_OB_APP_NAME(UTF8_STRING) = "limebar"
_OB_APP_ROLE(UTF8_STRING) =
_NET_WM_VISIBLE_ICON_NAME(UTF8_STRING) = "bar"
_NET_WM_VISIBLE_NAME(UTF8_STRING) = "bar"
WM_CLASS(STRING) = "limebar", "", "", "", "", ""
WM_NAME(STRING) = "bar"
_NET_WM_STRUT(CARDINAL) = 0, 0, 20, 0
_NET_WM_STRUT_PARTIAL(CARDINAL) = 0, 0, 20, 0, 0, 0, 0, 0, 1920, 3840, 0, 0
_NET_WM_DESKTOP(CARDINAL) = 4294967295
_NET_WM_STATE(ATOM) = _NET_WM_STATE_ABOVE
_NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_DOCK
Now of course there's some extra info in the C++ version's output but it is my understanding that it's only _NET_WM_STRUT and _NET_WM_STRUT_PARTIAL that matter when it comes to reserving space. What am I missing here?

Your working example has a WM_STATE property. The non-working does not.
This property is set by the window manager when it manages a window. Are you perhaps creating an override-redirect window in the Rust version, but not in the C++ version?

Related

Get FileInfo with windows api

Im a bit new to rust. So im trying to fetch FileDescription from windows crate. Im failing to convert the descriptionBuffer from VerQueryValueA into utf8 string. Cant figure out what im doing wrong.
fn get_proc_data(pid: u32) -> Option<String> {
let mut path = None;
unsafe {
let h_snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);
if h_snap != INVALID_HANDLE_VALUE {
let mut mod_entry: MODULEENTRY32 = MODULEENTRY32 {
..Default::default()
};
mod_entry.dwSize = size_of_val(&mod_entry) as u32;
if Module32First(h_snap, &mut mod_entry).as_bool() {
let char_vec = mod_entry.szExePath.iter().map(|f| f.0).collect::<Vec<u8>>();
path = match from_utf8(&char_vec) {
Ok(s) => Some(String::from(s.to_string().trim_end_matches(char::from(0)))),
Err(_) => None,
};
}
}
CloseHandle(h_snap);
if path.is_some() {
let mut infoBuffer: [u8; 2048] = [0; 2048];
let pat = path.as_ref().unwrap();
let lpvoid: *mut c_void = infoBuffer.as_mut_ptr() as *mut c_void;
let c_str = CString::new(pat.as_str()).unwrap();
let pstr = PSTR(c_str.as_ptr() as *const u8);
let verInfoLen = GetFileVersionInfoSizeA(pstr, &mut 0);
let ok = GetFileVersionInfoA(pstr, 0, verInfoLen, lpvoid);
let mut descriptionBuffer: [u8; 256] = [0; 256];
let descriptionPtr: *mut *mut c_void =
descriptionBuffer.as_mut_ptr() as *mut *mut c_void;
let mut descriptionLen = 0;
if ok.as_bool()
&& VerQueryValueA(
lpvoid,
"\\StringFileInfo\\040904E4\\FileDescription",
descriptionPtr,
&mut descriptionLen,
)
.as_bool()
{
info!("{:?}", descriptionBuffer);
let res = from_utf8_lossy(&descriptionBuffer);
info!("{:?} {:?}", path, res);
}
}
}
return path;
}
Example outputs
info!("{:?}", descriptionBuffer);
INFO - [180, 162, 146, 165, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
info!("{:?} {:?}", path, res);
INFO - Some("C:\Users\acoop\AppData\Local\Amazon Music\Amazon Music.exe") "�����\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}"
Querying for file information properties is a multi-step process:
Determine the version info size by calling GetFileVersionInfoSizeW
Allocate a sufficiently sized buffer; a Vec provides everything needed (contiguous memory, runtime dynamic size, low stack memory overhead)
Read the entire version info into the allocated buffer by calling GetFileVersionInfoW
Query for the information of interest using VerQueryValueW; on success the function returns a pointer/size pair into the buffer allocated above
It is the final step that ultimately goes wrong in the code provided. The API expects the address of a pointer variable where it stores the result. The code however passes the address of the first element of descriptionBuffer, and that's where the API writes to (presumably, the code was compiled for a 64-bit target, meaning that the first 8 bytes are the pointer value).
In essence the code did succeed in producing a pointer/size pair, but failed to interpret them according to the API contract. An improved version that queries for a binary's file description might look like this:
fn get_file_description(path: impl AsRef<Path>) -> Result<String, Box<dyn Error>> {
// Determine version info size
let size = unsafe { GetFileVersionInfoSizeW(path.as_ref().as_os_str(), null_mut()) };
if size == 0 {
return Err(core::Error::from_win32().into());
}
// Allocate buffer
let mut buffer = vec![0u8; size as usize];
// Read version info
unsafe {
GetFileVersionInfoW(
path.as_ref().as_os_str(),
0,
size,
buffer.as_mut_ptr() as *mut std::ffi::c_void,
)
}
.ok()?;
// Declare pointer/size pair for output
let mut ptr = null_mut();
let mut len = 0;
// Query for file description
let success = unsafe {
VerQueryValueW(
buffer.as_ptr() as *const std::ffi::c_void,
"\\StringFileInfo\\040904B0\\FileDescription",
&mut ptr,
&mut len,
)
}
// The API call doesn't set the last error code so we cannot use `.ok()?` here
.as_bool();
if !success {
return Err("Failed to query file description".into());
}
// `len` here is in elements (as opposed to bytes)
let descr = unsafe { slice::from_raw_parts(ptr as *const u16, len as usize) };
// Optionally use `from_utf16_lossy` if you don't need to handle invalid UTF-16
let descr = String::from_utf16(descr)?;
Ok(descr)
}
This is better, but certainly not perfect by any stretch of the term. Most of the improvements revolve around character encoding subtleties, the gnarliest of pain points when it comes to Rust on Windows. There is no dedicated string type in Rust that can store strings in Windows' native character encoding, UTF-16.
Noteworthy changes:
The function accepts an argument convertible to a Path reference. The underlying storage is of type OsStr, sporting a relaxed version of UTF-8 capable of representing any sequence of UTF-16 code units, well-formed or otherwise. This is crucial since Windows makes no character encoding guarantees with respect to filesystem objects. With the exception of a few reserved values, virtually any sequence of 16-bit values is allowed. Your program needs to be prepared for this.
All narrow-character set versions of the API calls have been replaced with the wide-character versions (see Conventions for Function Prototypes for background information). This is the only safe option when dealing with data you do not control (such as version info resources of arbitrary binaries). Of particular note here is that the windows crate provides an implicit conversion from &OsStr into PCWSTR, so passing a Path into wide-character APIs isn't entirely inconvenient (but they do incur a conversion and allocation).
Likewise, the windows crate provides conversions from &str to PCWSTR, gated under the "alloc" feature. This allows using a string literal in the call to VerQueryValueW and get everything converted as needed (again, with a conversion and allocation cost).
To turn this into a fully working example, that produces a command line application accepting the path name of the binary image as its first argument, simple add the following Cargo.toml
[package]
name = "fileinfo"
version = "0.0.0"
edition = "2021"
[dependencies.windows]
version = "0.33.0"
features = [
"alloc",
"Win32_Foundation",
"Win32_Storage_FileSystem",
]
and add the following to the src/main.rs file:
use std::{env, error::Error, path::Path, ptr::null_mut, slice};
use windows::{
core,
Win32::Storage::FileSystem::{GetFileVersionInfoSizeW, GetFileVersionInfoW, VerQueryValueW},
};
fn main() -> Result<(), Box<dyn Error>> {
let input = env::args_os()
.nth(1)
.ok_or("Expected 1 command line argument")?;
let path = Path::new(&input);
let descr = get_file_description(&path)?;
println!("File description: \"{}\"", &descr);
Ok(())
}

Ruby-Sketchup change color of faces

I would like to color the top of this shape to rfClr, any ideas? I can change the whole thing Grey, but how to change the top to blue?
l=100
w=60
h=20
hl=8
slope=4
clr='Gray'
rfClr='blue'
ent = Sketchup.active_model.entities
#---------Clear All
Sketchup.active_model.entities.clear!
#----------------
model = Sketchup.active_model
model.start_operation "Create Box"
#-----------------------------------------------------------------------------
entities = model.active_entities
group = entities.add_group
entities = group.entities
group.name="Box"
#pt0 = [0, 0, 0]
#pt1 = [0, 0, h*12+hl]
#pt2 = [w*12/2, 0, 12*h+hl+(w/2)*slope]
#pt3 = [w*12, 0, 12*h+hl]
#pt4 = [w*12, 0, 0]
newface = entities.add_face(#pt0, #pt1, #pt2, #pt3 , #pt4)
newface.material=Sketchup::Color.new clr
#newface.reverse!
newface.pushpull l*12
I found this answer.
I guess it finds the faces that have a z value
vfaces = entities.grep(Sketchup::Face).find_all{|f| f.normal.z.abs != 0 }
vfaces.each{|f| f.material = rfClr }

D3 Chord Diagram Not Rendering Correctly

Using the excellent guide by Nadieh Bremer I'm making a stretched chord diagram.
However, with certain data inputs the rendering goes awry.
I've made a demo to demonstrate my issue here:
https://codepen.io/benmayocode/pen/MPEwdr
Specifically, in the .js file lines 269 to 281 file I have:
var respondents = 40,
emptyPerc = 0.4,
emptyStroke = Math.round(respondents*emptyPerc);
var Names = ['BEN', 'ROSE', '', '1', '2', '6', ''];
var matrix = [
[0, 0, 0, 10, 10, 0, 0] ,
[0, 0, 0, 0, 10, 10, 0] ,
[0, 0, 0, 0, 0, 0, 24] ,
[10, 0, 0, 0, 0, 0, 0] ,
[10, 10, 0, 0, 0, 0, 0] ,
[0, 10, 0, 0, 0, 0, 0] ,
[0, 0, 0, 24, 0, 0, 0] ,
];
This renders incorrectly - but if I change it to...
var respondents = 40,
emptyPerc = 0.4,
emptyStroke = Math.round(respondents*emptyPerc);
var Names = ['BEN', 'LIB', 'ROSE', '', '1', '2', '6', ''];
var matrix = [
[0, 0, 0, 0, 10, 10, 0, 0] ,
[0, 0, 0, 0, 0, 10, 0, 0] ,
[0, 0, 0, 0, 0, 10, 10, 0] ,
[0, 0, 0, 0, 0, 0, 0, 24] ,
[10, 0, 0, 0, 0, 0, 0, 0] ,
[10, 10, 10, 0, 0, 0, 0, 0] ,
[0, 0, 10, 0, 0, 0, 0, 0] ,
[0, 0, 0, 0, 24, 0, 0, 0] ,
];
Then it works great. I obviously see the difference between the two blocks of code, but why are they producing different results, and is it possible to modify my code to accommodate both examples?
If you examine the dodgy arc, you will see you can flip it into the right place by altering the sign on the transform from (50,0) to (-50,0). If you then look at the code that assigns the transform, it is
.attr("transform", function(d, i) {
d.pullOutSize = pullOutSize * ( d.startAngle + 0.01 > Math.PI ? -1 : 1);
return "translate(" + d.pullOutSize + ',' + 0 + ")";
});
with a note in the original text to say that "the 0.01 is for rounding errors". Given that the startAngle is already 3.13--i.e. very close to Pi--it looks like this is an edge case where the value fell just the wrong side of the cutoff. Changing the allowable rounding error value to 0.02 puts the arc in the correct place, or you could do something like
d.pullOutSize = pullOutSize * (
// is the start angle less than Pi?
d.startAngle + 0.01 < Math.PI ? 1 :
// if yes, is the end angle also less than Pi?
d.endAngle < Math.PI ? 1 : -1 );
to prevent edge cases like that in your dataset.

WebGL LookAt works on -z but broke on +z?

I'm trying to build my own camera class in WebGL for learning purposes. It's almost complete but I have 1 slight issue with the lookAt function. If I translate my object in the -z direction then it will work fine but once I move it in the +z direction it acts as if it's doing the opposite and the object will begin to stretch across the screen if I move the camera up or down.
This is what I currently have:
var zAxis = new Vector(cameraPosition.x, cameraPosition.y, cameraPosition.z)
.subtract(target)
.normalize();
var xCross = math.cross(up.flatten(3), zAxis.flatten(3));
var xAxis = new Vector(xCross[0], xCross[1], xCross[2]).normalize();
var yCross = math.cross(zAxis.flatten(3), xAxis.flatten(3));
var yAxis = new Vector(yCross[0], yCross[1], yCross[2]).normalize();
var orientation = [
xAxis.x, xAxis.y, xAxis.z, 0,
yAxis.x, yAxis.y, yAxis.z, 0,
zAxis.x, zAxis.y, zAxis.z, 0,
0, 0, 0, 1
];
var translation = [
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
cameraPosition.x, cameraPosition.y, cameraPosition.z, 1
];
this.multiply(translation);
this.multiply(orientation);
Does anyone know what I've done wrong?

Does XGetImage ever return a 32-bit depth XImage?

I am using XGetImage to read the pixels of an OpenGL window. The XImage that is returned shows a depth of 24-bits, but my OpenGL context has alpha values that I would like to be returned. Is there any way to get a 32-bit XImage from XGetImage, or does X already flatten the image to 24-bits?
Function call:
::XImage *winImage = XGetImage(dpy_i->dpy, wnd_i->wnd,
x, y, width, height, 0xffffffff, ZPixmap);
GDB output:
(gdb) print *winImage
$2 = {width = 640, height = 512, xoffset = 0, format = 2,
data = 0x7fffe72fd010 "\377\377\377", byte_order = 0,
bitmap_unit = 32, bitmap_bit_order = 0, bitmap_pad = 32,
depth = 24, bytes_per_line = 2560, bits_per_pixel = 32,
red_mask = 16711680, green_mask = 65280, blue_mask = 255,
obdata = 0x0, f = {create_image = 0x7ffff4b67810 <XCreateImage>,
destroy_image = 0x7ffff4b665b0, get_pixel = 0x7ffff4b67520,
put_pixel = 0x7ffff4b67450, sub_image = 0x7ffff4b67170,
add_pixel = 0x7ffff4b66650}}
I seem to always get a 32bit image. This is my code, js-ctypes, i take a screenshot of all monitors.
https://github.com/Noitidart/_scratchpad/blob/c41012b16842f0769595033bd51a3801451319be/x11%20new%20way%20skel%20non%20jsm.js
This is my XImage struct after XGetImage:
"width:" "1280" "height:" "919" "xoffset:" "0" "format:" "2" "data:" "ctypes.char.ptr(ctypes.UInt64("0x7f850fe00000"))" "byte_order:" "0" "bitmap_unit:" "32" "bitmap_bit_order:" "0" "bitmap_pad:" "32" "depth:" "24" "bytes_per_line:" "5120" "bits_per_pixel:" "32" "red_mask:" "16711680" "green_mask:" "65280" "blue_mask:" "255" "_END_"

Resources