How do I suppress a window background paint in XLib? - x11

I'm new to X and Linux programming in general. It's pretty easy to suppress a window background repaint (to reduce flicker when the window is resized) using VC++ and Windows. However the architecture and difficulty in finding comprehensive documentation for X is a different game altogether.

You can create a pixmap which will serve as an offscreen temporary buffer, draw into it, and after all drawing operations have been completed update the window background only once:
Pixmap pixmap = XCreatePixmap(display,
rootWindow,
width,
height,
XDefaultDepthOfScreen(screen));
// Draw into pixmap
// ...
// ...
// And update window background after that
XSetWindowBackgroundPixmap(display, window, pixmap);
XClearWindow(display, window);

Related

How do I force a repaint of only the background so a control doesn't repaint over it again?

This question was generated by a response to another question: Common Controls on a Transparent Window?.
Apparently, there is a way to only paint the background without a control painting itself again This would solve the problem of having common control buttons on a transparent background.
So my question is, how do I paint only the background around a common control after the common control has painted itself?
About how to redraw visible borders.
The rounded rectangle drawn by RoundRect is used as representative
The FrameRgn function draws a border around the specified region by using the specified brush.
Simple code demonstration:
HRGN hRegion = ::CreateRoundRectRgn (0, 0, ClientWidth, ClientHeight,12,12);
Canvas->Brush->Style = bsSolid;
Canvas->Brush->Color = RGB(96, 96, 96);
::FrameRgn(Canvas->Handle, hRegion, Canvas->Brush->Handle, 2, 2);
::DeleteObject(hRegion); // Don't leak a GDI object
Link you need: Redraw Border

Resizing Layered Windows

I'm hoping I can get away with communicating the issue I'm having clearly without posting a ton of source code. The source is all ASM and while most would understand it, it's still not their primary "thing."
I have a layered window which is working perfectly - up to the point of resizing it. The window is all per-pixel alpha. There are no transparent pixels. The borders and caption are opaque (255 alpha); the client area is something like 128 alpha or whatever I put it at. So no transparent pixels.
I have a function that handles redraws - it's actually geared toward rebuilding the frame for a new window size. GetWindowDC is called on the layered window. CreateCompatibleDC creates off of that DC. The bitmap is a DIB section. The bitmap is properly sent to UpdateLayeredWindow. Again, everything works perfectly as long as the window is not in active resize (border drag).
I have tried using DefWindowProc to handle border drags, as well as completely handling all aspects of that functionality myself. The results are the same: massive flicker but ONLY beyond the window boundaries that existed before border drag began, and then the window size does not ultimately change - sort of. The original window area remains displayed without issue. No flicker there. However if (for example) I'm dragging the right border to the right, everything right of the original window right edge flickers rapidly then vanishes. When I release the left mouse button, the display remains at the original size (the size the window was before dragging the border). I've verified the bitmap is correctly rebuilt to the new size. It seems like the DC for the layered window doesn't want to resize because the entire area of original window size is completely stable, but any new area appearing post-resize flickers then hides.
I've even tried removing the ws_ex_layered style before resizing the window in my manual handling (I've tried both MoveWindow and SetWindowPos) then resetting the ex style after SetWindowPos / MoveWindow but before dragging.
When I let DefWindowProc handle the updates, I got the exact same result. So indications are that something is wrong with my repainting. But I even whittled that process down (commenting out oodles of code for test) and just filled the bitmap with 0xFF0000FF (arbitrary test value, blue, full opacity) then jumped straight to UpdateLayeredWindow. Same result.
The bitmap used for UpdateLayeredWindow is deleted before calling the "rebuild" function and within the function that bitmap is recreated to the new size. I have verified the new size extensively - I can see the new bitmap as it high-speed flickers and it's all good. The DC is GetWindowDC from the layered window. The compatible DC creates off that DC. The bitmap is selected into the compatible DC, and that compatible DC is passed to UpdateLayeredWindow. If any of these things were off, I would never see the new bitmap displayed. It's there - it just flickers at high speed ONLY beyond the window bounds that existed before resize began. DefWindowProc yields the same results. Within that original area, my caption buttons slide off to the right as I drag the right border to the right, further verifying everything is good.
I'm at a loss. Any input would be welcome.

Read image behind current window

In Win32 or Direct2D, is it possible to read the screen that would be under the window that is being drawn? (in OnPaint() or wherever) Is it necessary to generate the screen data in back of the current window's rectangle and blit it into a memory buffer, and is this possible?

Clearing a window contents in a blur behind window(DWM)

I have a window on which I call DwmExtendFrameIntoClientArea(),
the window hosts other child windows, I use Direct2D to paint on one of the child windows,
When a bitmap is loaded which has a black region on it, that region becomes blurred.
I wish to clear everything in the child window and paint it again on WM_PAINT, however I cannot seem to clear the contents.
I have tried to clear it using
m_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::Black))
This makes the child window region black, it erases all previous drawing, but no transparency.
I have tried to draw a bitmap which is just a black bar over the client area
m_pRenderTarget->DrawBitmap(m_pBkgrnd,D2D1::Rect<float> (0.f,0.f,GetWidth(),GetHeight()))
This makes whatever that had appeared before it, in black.
Tried the old GDI way of painting a black region over the entire child window,
RECT rc;
GetClientRect(m_hwnd, &rc);
HBRUSH brush = CreateSolidBrush(RGB(0,0,0));
HDC hc=GetDC(m_hwnd);
FillRect(hc, &rc, brush);
ReleaseDC(m_hwnd,hc);
DeleteObject(brush);
Doesn't work.
However if I don't do any of this and I try to resize the main window, it works right i.e. the previous painting dissappears.
Is there any API call or any way to clear the window manually before I draw it again?
How are you initializing your render target? Make sure you specify Premultipled Alpha, and not Straight or Ignore. Then, to clear everything to transparent, use ID2D1RenderTarget::Clear(D2D1::ColorF(0, 0, 0, 0)). You cannot use something like FillRectangle to draw with a transparent color, as that will blend the transparent color into what's already there and that is a no-op.

How to draw PNG over dialog controls

I need to make some thing like a SEMI-transparent glass layer over dialog's controls. The context is when my application wait for a long process to finish all other controls need to be disabled, and an animation is shown on glass layer as waiting-animation.
I am going to draw a semi-transparent PNG image with size of client area, overlapping all other controls. I do the drawing in OnPaint() but image is drawn as background of the dialog.
So my question is how can i draw png image overlap dialog's control??
LRs
You can try with fiddling the WS_CLIPCHILDREN and WS_CLIPSIBLINGS styles, but I'm not sure that will work. I think you will need to draw a custom control on top of all other controls (at the top of the z-order stack) and draw your bitmap on that one (that's the approach I would take - the dialog is supposed to be behind the controls always, so your approach of drawing on the dialog is fighting the system, as it were).
So basically you would draw on the custom control that would cover all other controls, but you don't even need to draw it transparently; you can use the WS_EX_TRANSPARENT and/or WS_EX_LAYERED window style and SetLayeredWindowAttributes() method, as long as you don't need to support operating systems older than win2k.

Resources