Creating subwindow fails with BadRegion? - rust

In trying to fix https://stackoverflow.com/a/69647995?noredirect=1, I had an idea; what if I drew the things (that were failing to draw directly on the window) in subwindows of the frame window? It looks like other WMs like Openbox also took this approach.
So I tried doing this:
let text_win = self.conn.generate_id()?;
let text_win_aux = xproto::CreateWindowAux::new()
.event_mask(
xproto::EventMask::EXPOSURE
| xproto::EventMask::SUBSTRUCTURE_REDIRECT
| xproto::EventMask::SUBSTRUCTURE_NOTIFY
| xproto::EventMask::BUTTON_PRESS
| xproto::EventMask::BUTTON_RELEASE
| xproto::EventMask::POINTER_MOTION
| xproto::EventMask::ENTER_WINDOW
| xproto::EventMask::PROPERTY_CHANGE,
)
.background_pixel(0xFFFFFF);
self.conn.create_window(
COPY_DEPTH_FROM_PARENT,
text_win,
frame_win,
15,
15,
60,
25,
0,
xproto::WindowClass::INPUT_OUTPUT,
screen.root_visual,
&text_win_aux,
)?;
self.conn.map_window(text_win)?
But it doesn't work (there is no white rectangle rendered), and it looks like I get a BadRegion error too.
What I expect is that a white rectangle is rendered on the frame window (as the background_pixel of the child is white, and I map it to the frame).
What could I be doing wrong? This doesn't seem to be affected by depth, btw.

I've figured it out. The "text_win" needs to be using the same visual as the frame window; I accidentally used the X11 screen's root visual instead.
So this create_window call functions as expected:
.background_pixel(0xFFFFFF);
self.conn.create_window(
COPY_DEPTH_FROM_PARENT,
text_win,
frame_win,
15,
15,
60,
25,
0,
xproto::WindowClass::INPUT_OUTPUT,
attr.visual,
&text_win_aux,
)?;
(Also, I discovered that the BadRegion was something else, it was a xcompmgr bug, nothing related to this)

Related

how to get height of an entity in ursina?

I'm making a Brick Breaker Game using Ursina in python. I've created some entities which work as ball and bar.
bar = Entity(model='quad', color=color.blue, position=(4.5, -10, 0), scale=(3, 0.3), collider='box')
ball = Entity(model='sphere', color=color.red, position=(4.5, -9.5, 0), scale=0.25, collider='sphere')
I want the ball at the upper center of the bar without manually setting the x and y value. Like this:
For this I want the width and height of the bar. How can I get that? I tried bar.width. But it returns 'Entity' object has no attribute 'width'
Yes, it is possible. You can use bar.scale_x and bar.scale_y.
For more options you can check https://www.ursinaengine.org/api_reference and see Entity (https://www.ursinaengine.org/api_reference#Entity)

Using CMFCMenuButton::SizeToContent does not seem to work as I would like. Why?

I am perplexed about the SizeToContent method of the CMFCMenuButton control.
This is my dialog in the IDE:
As you can see, I have specifically made the button wider than the two on the far right.
I added the following code to OnInitDialog:
// Resize (if required)
const auto sizNewButton = m_btnReset.SizeToContent(true);
CRect rctButton;
m_btnReset.GetWindowRect(&rctButton);
if(sizNewButton.cx > rctButton.Width())
{
m_btnReset.SizeToContent();
}
Yet, when I run my application in English:
It has made it smaller. My application supports 50+ languages by using satellite DLLs and I was hoping to only resize to content if it was required. But it seems to resize it anyway. Have I missed a step here?
I have checked the properties for the control in the IDE and it is not set to auto resize:
I notice that the help documentation states:
The new size of the button is calculated to fit the button text, image, and arrow. The framework also adds in predefined margins of 10 pixels for the horizontal edge and 5 pixels for the vertical edge.
I had a look at my button:
Default size: 48 x 23 (the GeWindowRect result).
Calculated size: 57 x 23 (the SizeToContent result).
If I adjusted my code like this:
if((sizNewButton.cx - 10) > rctButton.Width())
That would bring it down to 47 and thus would not resize. I am assuming the code is not working right because of the padded margin that GetWindowRect knows nothing about.
Searched it, and found that the problem is MFC's CMFCMenuButton::SizeToContent() implementation in afxmenubutton.cpp:
CSize CMFCMenuButton::SizeToContent(BOOL bCalcOnly)
{
CSize size = CMFCButton::SizeToContent(FALSE); // <==== The culprit!!!
size.cx += CMenuImages::Size().cx;
if (!bCalcOnly)
{
SetWindowPos(NULL, -1, -1, size.cx, size.cy, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
}
return size;
}
That is, it calls the base implementation of SizeToContent() with the bCalcOnly parameter set to FALSE, which means it will also resize the control to just fit the text (without the drop-down arrow). This is less than required for the text plus the arrow, and of course the original size is lost.
A workaround can be get the (original) width, before the SizeToContent() call, and work with this instead of the new one:
CRect rctButton;
m_btnReset.GetWindowRect(&rctButton);
const auto nOrigWidth = rctButton.Width(); // Store the original width
const auto sizNewButton = m_btnReset.SizeToContent(true); // This resizes the control!!!
if (sizNewButton.cx > nOrigWidth) // Compare to the original width rather than the new one
m_btnReset.SizeToContent();
else // Restore original width
m_btnReset.SetWindowPos(NULL, -1, -1, nOrigWidth, sizNewButton.cy, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
Alternative Workaround:
Define a new CMFCMenuButton-based class, overriding SizeToContent() - in the implementation call the base CMFCButton::SizeToContent() with the bCalcOnly parameter passed by the caller, not with FALSE. Map the control to this class instead of CMFCMenuButton. That is use a class that fixes it. Too much of an overkill for just a workaround though.

How can I display the IDI_INFORMATION icon at 16 x 16 in the lower left of my dialog?

When you use a CTaskDialog you can set the footer icon, which is 16 x 16. I would like to do something similar on my own dialog:
At the moment my own dialog has a static resource at the bottom.
I know that I can load the information icon like this:
HICON hInfo = LoadStandardIcon(IDI_INFORMATION);
How do we load it as 16 x 16?
How do we display it on the left on the dialog?
If you (hopefully) don't need to support Windows XP, you can use LoadIconWithScaleDown
For example:
HICON hicon;
HRESULT hr = LoadIconWithScaleDown(NULL, (PCWSTR)IDI_INFORMATION,
GetSystemMetrics(SM_CXICON) / 2, GetSystemMetrics(SM_CYICON) / 2, &hicon);
...
This gives you the additional benefit of loading the modern version of the icons instead of the old ugly ones. See also this SO article.
You could do it by using Picture Control, and position it whenever you want. And as code you could do:
CStatic myicon;
myicon.Attach(GetDlgItem(ID_STATIC_ICON));
myicon.SetIcon(static_cast<HICON>(::LoadImage(nullptr, MAKEINTRESOURCE(IDI_MYICON), IMAGE_ICON, 16, 16, 0)));
I didn't test the code, but should work.

Get and set correct window position with node.js

In the close event I persist the window position as follows:
localStorage.lastlayout = JSON.stringify({
"left": win.x,
"top": win.y,
"width": win.width,
"height": win.height
});
On start, I restore it with:
data = JSON.parse(localStorage.lastlayout);
win.moveTo(data.left, data.top);
win.resizeTo(data.width, data.height);
The problem is the position is off. As far as I can tell, I get the inner position. When setting I set the outer position. The windowing title and borders only accounted for when setting.
As this is cross-platform code I cannot test it on all platforms (yet) and I don't know if it is possible to get the metrics of the windowing engine so that I can correct it programmatically (think about the user changing the DPI or theme on Windows).
Is there a way to compensate for this?
Ok, I've nailed it. I detect the offsets in respect to a known position (0, 0) and then detract it from the desired position. It's not perfect but it works:
win.resizeTo(128, 128);
win.moveTo(0, 0);
log("dbg", "win", "detected metrics: " + win.x + ", " + win.y);
win.moveTo(data.left - win.x, data.top - win.y);
win.resizeTo(data.width, data.height);
The initial resize is necessary for some reason. It looks like the title and borders are not drawn at all on some platforms if the window is not large enough. Next I move it to the origin. The win.x and win.y contain the offsets at this point. The second moveTo() uses the corrected coordinates and finally I resize the window to the actually desired size.

Python Cocos2d Label class is ignoring color

I'm using the Python Cocos2D game library and in their docs you can find cocos.text.Label which accepts color=RGBA(int, int, int, int) as params. I've got the following code create a Label:
self.name = cocos.text.Label("Test Label",
font_name='Times New Roman',
font_size=22,
color=(163, 42, 44, 1),
anchor_x='center', anchor_y='center')
self.name.position = (10, 90)
self.add(self.name)
This code is attached to a cocos.layer.Layer and rendered in a Scene initiated in the director.
The issue is this: if I remove the color param from the Label the Label is created correctly and displayed as White color, but if specified color, then the label is just never rendered. Not even black its just not there.
Any help on why this is happening and how to change Label color is very appreciated.
I'm using python 3.4.3 and latest version of python-cocos2d. I'm willing to update and post any code so feel free to ask. Thanks in advance.
Maybe you just can't see the label? The A in RGBA goes from 0 to 255. Value 1 is almost transparent. Try color=(163, 42, 44, 255).

Resources