How to get inner and outer window dimensions with Xlib/XCB? - xlib

Is there a reliable way to get the inner and outer rectangle of a top
level window with XCB/Xlib? (IOW frame and client rectangle).
Here's what I tried:
xcb_get_geometry always returns the initial dimensions even after
the window gets resized (what gives?)
I figured I would call xcb_query_tree repeatedly until I find the
window's frame window - is this the way to do it? I figure ICCCM/EWMH
should provide this but couldn't find anything. Is there any other
standard/non-standard for this? Anyway that doesn't work with
compiz/ubuntu10 because xcb_query_tree reports the client window as
having root = parent (under normal ubuntu wm the window gets properly
reparented).
xcb_translate_coordinates() seemed to be the only reliable way to
get root-based coords[1] in 2007 -- is this still the case? I.e. is
XCB_CONFIGURE_NOTIFY non-standard with WMs?
[1] http://fixunix.com/xwindows/91652-finding-position-top-level-windows.html

This is a partial answer as it only explains how to find the inner dimensions of a window. Also I am not sure if this is the canonical way to go but it works for me.
You can subscribe to the XCB_EVENT_MASK_RESIZE_REDIRECT event when creating a window:
xcb_window_t window = xcb_generate_id (connection);
const xcb_setup_t *setup = xcb_get_setup (connection);
xcb_screen_t *screen = xcb_setup_roots_iterator (setup).data;
uint32_t mask = XCB_CW_EVENT_MASK;
uint32_t valwin[1] = { XCB_EVENT_MASK_EXPOSURE
| XCB_EVENT_MASK_RESIZE_REDIRECT };
xcb_create_window(
connection,
XCB_COPY_FROM_PARENT,
window,
screen->root,
0, 0,
800, 600,
0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen->root_visual,
mask, valwin);
xcb_map_window(connection, window);
xcb_flush(connection);
In the event loop you can then keep track of resizes:
xcb_generic_event_t *event;
uint16_t width = 0, height = 0;
while ((event = xcb_wait_for_event(connection)) != NULL) {
switch (event->response_type & ~0x80) {
case XCB_EXPOSE: {
/* ... */
break;
}
case XCB_RESIZE_REQUEST: {
auto resize = (xcb_resize_request_event_t*) event;
if (resize->width > 0) width = resize->width;
if (resize->height > 0) height = resize->height;
break;
}
default:
break;
}
free(event);
xcb_flush(connection);
}
Note that I am not sure whether this event is emitted when you initiate the resize from your application code using xcb_configure_window for example. I never tested it and just update the width and height in a wrapper function for xcb_configure_window.

Related

Set position not updated when open another tab

I do a growth animation of a fixed number of items, and after growth, i moved it to left.
Make growth by apply matrix
var trans_vector = new THREE.Matrix4().makeTranslation(0, height / 2, 0);
var graphics = new Graphics();
var rectangle = graphics.box(width, height, material);
rectangle.geometry.applyMatrix(trans_vector);
When a new item is added, i remove one from the container that will be added to scene
var children = this.container.children;
if (this.current_number === this.max_number) {
this.container.remove(children[0]);
this.current_number = this.max_number - 1;
}
object.position.copy(this.position); // this is a fixed position
this.container.add(object);
this.current_number++;
I write a function to translate to left, using tweenjs (sole)
animateTranslation : function(object, padding, duration) {
var new_x = object.position.x - padding; // Move to left
console.log(new_x); // Duplicated item here :(
new TWEEN.Tween(object.position).to({
x : new_x
}, duration).start();
},
And I remove all the "previous" items, using for loop
for (var i = 0; i < this.current_number-1; i++) {
this.animateTranslation(this.container.children[i],
this.padding,
this.duration/4)
}
The above code run correctly if we open and keep this current tab.
The problem is when we move to another tab, do something and then move back, some objects have the same position, that cause the translation to the same position. It looks weird.
It appears on both Chrome, Firefox and IE11.
I dont know why, please point me out what happened.
Most modern browsers choose to limit the delay in setInterval and pause requestAnimationFrame in inactive tabs. This is done in order to preserve CPU cycles and to reduce power consumption, especially important for mobile devices. You can find more details about each browser in this answer
That means, while the tab is inactive, your tween animation is not working the way it is normally expected to.
A simple solution would be to halt the main animation loop if the tab is inactive using a variable.
window.onfocus = function () {
isActive = true;
};
window.onblur = function () {
isActive = false;
};

Can't change tooltip coordinates MFC

I need to make tooltip a little bit right and lower to mouse cursor, but i can't do it in any way, tried different coordintaes but nothing seems to work. Where is the problem? Thank you.
// Add the new tooltip (if available)
if (m_LastToolTipRow!=-1 && m_LastToolTipRow!=-1)
{
// Not using CToolTipCtrl::AddTool() because it redirects the messages to CListCtrl parent
TOOLINFO ti = {0};
ti.cbSize = sizeof(TOOLINFO);
ti.uFlags = TTF_IDISHWND | TTF_TRANSPARENT; // Indicate that uId is handle to a control
ti.uId = (UINT_PTR)m_hWnd; // Handle to the control
ti.hwnd = m_hWnd; // Handle to window to receive the tooltip-messages
ti.hinst = AfxGetInstanceHandle();
ti.lpszText = LPSTR_TEXTCALLBACK;
m_OwnToolTipCtrl.SendMessage(TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);
m_OwnToolTipCtrl.SendMessage(TTM_TRACKPOSITION, 0, (LPARAM)MAKELPARAM(pt.x + 100, pt.y + 100));
m_OwnToolTipCtrl.SendMessage(TTM_TRACKACTIVATE, true, (LPARAM)&ti);
m_OwnToolTipCtrl.Activate(TRUE);
//Multiline
m_OwnToolTipCtrl.SetMaxTipWidth(256);
//m_OwnToolTipCtrl.SetMaxTipWidth(SHRT_MAX);
}
TTF_IDISHWND
Indicates that the uId member is the window handle to the tool. If this flag is not set, uId is the tool's identifier.
According to this, the window with m_hWnd handle is the one that shows the tooltip and you can position the window itself. If you meant a tooltip separate to that window than there is a principal problem there.

CRect member variables have strange values

I'm trying to use the member variables from my client rect, but they are holding extremely negative values, like -858993460. Even when I call rect.Width(), it returns an extremely negative number. I need the values to determine the corresponding section of a wave file to play when I select the wave that I have drawn on the screen. Would anyone happen to know why it could be doing this?
Note: I threw int's right, left, and width in just to see what values they are holding. I really only need rect.Width() to scale the selection to be able to access the data array of my wave file.
void CWaveEditView::OnToolsPlay32775()
{
// TODO: Add your command handler code here
CWaveEditDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if(!pDoc){
return;
}
if(pDoc->wave.hdr==NULL){
return;
}
if(selectionStart!=selectionEnd){
CRect rect;
GetClientRect(&rect);
rect.NormalizeRect();
int right = rect.right;
int left = rect.left;
int width = rect.Width();
int startms=(1000.0*pDoc->wave.lastSample/pDoc->wave.sampleRate)*selectionStart/rect.Width();
int endms=(1000.0*pDoc->wave.lastSample/pDoc->wave.sampleRate)*selectionEnd/rect.Width();
WaveFile * selection = new WaveFile(pDoc->wave.numChannels, pDoc->wave.sampleRate, pDoc->wave.bitsPerSample);
while(startms<=endms){
selection->add_sample(pDoc->wave.get_sample(startms));
startms++;
}
selection->updateHeader();
selection->play();
delete selection;
}
The default constructor of CRect does not initialise its members (because it is a thin wrapper for the RECT structure). You could initialise it to (0,0,0,0) and check whether or not it is empty after your call to GetClientRect.
Since GetClientRect appears to be failing, you may want to check that your window handle is valid using GetSafeHwnd().

Creating X11 window to span multiple displays

I'm having the exact problem described here. How to make X11 window span multiple monitors
I have six monitors and am trying to create a window larger than the size of one of the monitors. It keeps getting resized by the window manager.
Apologize if I should post within that thread, the etiquette is not clear to me.
Anhow, I do the following in my code:
/* Pass some information along to the window manager to size the window */
sizeHints.flags = USSize; // | PMinSize;
sizeHints.width = sizeHints.base_width = width;
sizeHints.height = sizeHints.base_height = height;
// sizeHints.min_width = width;
// sizeHints.min_height = height;
// sizeHints.max_width = mScreenWidth;
// sizeHints.max_height = mScreenHeight;
if (geometry->x != DONT_CARE && geometry->y != DONT_CARE) {
sizeHints.x = geometry->x;
sizeHints.y = geometry->y;
sizeHints.flags |= USPosition;
}
XSetNormalHints(mDisplay, mWindow, &sizeHints);
SetTitle(suggestedName);
XSetStandardProperties(mDisplay, mWindow,
suggestedName.toAscii(), suggestedName.toAscii(),
None, (char **)NULL, 0, &sizeHints);
/* Bring it up; then wait for it to actually get here. */
XMapWindow(mDisplay, mWindow);
The problem I'm having is that if I set min_width and min_height, the user cannot resize the window, which is not what I want. But if I don't, then when I do any X11 call later, such as
XGetWindowAttributes(mDisplay, mWindow, &win_attributes);
the window manager resizes my window to fit into one monitor instead of being larger than the monitor. I cannot just get a window of the desired size for some reason. Note that WidthOfScreen and HeightOfScreen give me the combined width and height of all monitors as expected.
Can anyone help? I hope I'm explaining myself clearly enough.

Which API can be used to _capture_ the mouse when moving OS X "Carbon" windows?

On request I have implemented support for moving an OS X window by dragging it using an area within the content part of the window, i.e replicating the drag and move functionality of the title bar but in another area.
The problem I have yet to resolve is the fact that if the user drags the mouse quickly it can leave the window area and then no more mouse move events are received.
On windows this type of problem can simply be fixed by calling the win32 method SetCapture(), what's the corresponding OSX method?
This application is a cross platform C++ application using Carbon for the OS X specific parts. (And yes, I know all about the Cocoa benefits but this is an older code base and there no time nor money for a Cocoa port at this point in time.)
I have found Carbon API methods like for example TrackMouseLocation() but can't really see how I could use them for this application. In listing 2-7 here http://developer.apple.com/legacy/mac/library/documentation/Carbon/Conceptual/Carbon_Event_Manager/Tasks/CarbonEventsTasks.html
the mouse is captured but the problem is that TrackMouseLocation() blocks waiting for input. Blocking is something this application can not do since it also host a flash player that must be called many times per second.
The protototype I have assembled when trying to figure this out basically looks like this:
switch(GetEventKind(inEvent))
{
case kEventMouseDown:
// A silly test to make parts of the window border "draggable"
dragging = local_loc.v < 25 || local_loc.h < 25;
last_screen_loc = screen_loc;
break;
case kEventMouseUp:
dragging = false;
break;
case kEventMouseMoved:
break;
case kEventMouseDragged:
if (dragging) {
Rect rect;
GetWindowBounds (windowRef, kWindowContentRgn, &rect);
int dx = screen_loc.h - last_screen_loc.h;
int dy = screen_loc.v - last_screen_loc.v;
rect.left += dx;
rect.right += dx;
rect.top += dy;
rect.bottom += dy;
SetWindowBounds (windowRef, kWindowContentRgn, &rect);
}
last_screen_loc = screen_loc;
break;
Any ideas appreciated?
I feel you should track mouse in Window as well as out of window. Following code should solve your problem,
EventHandlerRef m_ApplicationMouseDragEventHandlerRef;
EventHandlerRef m_MonitorMouseDragEventHandlerRef;
{
OSStatus ErrStatus;
static const EventTypeSpec kMouseDragEvents[] =
{
{ kEventClassMouse, kEventMouseDragged }
};
ErrStatus = InstallEventHandler(GetEventMonitorTarget(), NewEventHandlerUPP(MouseHasDragged), GetEventTypeCount(kMouseDragEvents), kMouseDragEvents, this, &m_MonitorMouseDragEventHandlerRef);
ErrStatus = InstallApplicationEventHandler(NewEventHandlerUPP(MouseHasDragged), GetEventTypeCount(kMouseDragEvents), kMouseDragEvents, this, &m_ApplicationMouseDragEventHandlerRef);
return true;
}
//implement these functions
OSStatus MouseHasDragged(EventHandlerCallRef inCaller, EventRef inEvent, void *pUserData){}
Hope it helps!!
I Hope It Help´s you too:
// Get Mouse Position --> WAY 1
printf("Get Mouse Position Way 1\n");
HICoordinateSpace space = 2;
HIGetMousePosition(space, NULL, &point);
printf("Mouse Position: %.2f %.2f \n", point.x, point.y);
// Get Mouse Position --> WAY 2
printf("Get Mouse Position Way 2\n");
CGEventRef ourEvent = CGEventCreate(NULL);
point = CGEventGetLocation(ourEvent);
printf("Mouse Position: %.2f, y = %.2f \n", (float)point.x, (float)point.y);
I´m looking for the way to get a WindowPart Reference at a certain location (over all windows of all aplications)
Certain methods in Carbon doesn´t work, always return 0 as a windowRef... Any ideas?
You could also try just calling DragWindow in response to a click in your window's content area. I don't think you need to implement the dragging yourself.

Resources