I noticed that if I unmap a window, when I map it back, it's maximized
state along with the restore-to size and position are all lost (Ubuntu
10). Is there a way to get the normal size/pos so I can put it back
before mapping? Or do I have to track it myself through resize events
(if that's even possible)?
Thanks.
This came up on a search when I noticed the same thing... so I'm not sure my answer is the best, but after looking at my window manager's source code and as many docs as I could (Xlib man pages, the ICCCM, EWMH spec), I couldn't find anything that did it automatically. XWithdrawWindow does basically the same thing as XUnmapWindow in my experiments and in my window manager's source and it was my best bet.
Looking at Qt's source code, it also has calls to adjust size when you call the show() method. So it must be necessary in at least some cases, if not all.
Sooo I think the answer is you need to track it yourself. ConfigureNotify events will tell you when you've been resized and I believe moved. You can watch for other properties like maximized through events too. If you keep track of these, you can move your window back.
Or you could ask for the size with XGetGeometry (and again other atom states too) before you do the unmapping.
Related
I'm looking at improving developer experience when running graphics tests which spawn short-lived windows "like crazy". The windows need to be physically there, as otherwise data readback fails (i.e. the window cannot be hidden)
Needless to say, windows popping up at high frequency is unpleasant. I set out with the goal of finding a way to tell XCreateWindow to "create the window in the background", "not to steal focus" or something like that to no avail. The closest thing I could find is calling XSetInputFocus post-creation. Other than the fact that I couldn't make it work, I don't expect setting input focus to fully solve the issue anyway (as the windows would still pop up, just not without input focus, right?).
How is this done in X11?
P.S. The update notification on Ubuntu starts without popping to front, so this must be a possibility.
In the past I've tried and admitedly failed doing what you want to do. Nevertheless I've found a few "close-enough"-solutions that may be of interest.
XCreatePixmap might work out, but in my case didn't have a pixmap with desired properties (multisampling) so it "out the window" (haha)
To prevent some level of spaming you might be able to set XCreateWindow parent to a an exisiting window other than root, large enough to hold your tests and moved outside display. The parent window need be created, moved outside display and un-focused, but at least every window creation won't steal focus (I think) and spam on display.
Or you figure out a way to create additional displays, maybe using Xvbf. Didn't have admin access to corp dev env so didn't bother trying to install/configure, in addition to other obstacles, but it might just work for you.
I have inherited a large MFC application which contains a CComboBox subclass that overrides OnPaint. Currently it does all its drawing by hand (with lines and rectangles), and renders a combo box that looks decidedly Windows 98-style. However, it otherwise works great and provides a lot of useful custom functionality that we rely on, and rewriting the entire control is probably not an option.
I would like to modernize it so that the OnPaint draws in Aero style where available (falling back to the old code when modern theming is unavailable). I've done this with some other custom controls we have, like buttons, and it works great for our purposes. I know there are some tiny behaviors that it won't get right, like gentle highlights on mouse-hover, but that's not a big deal for this app.
I have access to the CVisualStylesXP ckass, so I've already got the infrastructure to make calls like OpenThemeData, GetThemeColor or DrawThemeBackground pretty easily (via LoadLibrary so we don't force Vista as a min-system). Unfortunately, I don't know the proper sequence of calls to get a nice looking combo box with the theme-appropriate border and drop-down button.
Anyone know what to do here?
Honestly, I don't know why they originally tried to override OnPaint. Is there a good reason? I'm thinking that at least 99% of the time you are just going to want to override the drawing of the items in the ComboBox. For that, you can override DrawItem, MeasureItem, and CompareItem in a derived combo box to get the functionality you want. In that case, the OS will draw the non-user content specific to each OS correctly.
I think you best shot without diving in the depth of xp theming and various system metrics is take a look at this project: http://www.codeproject.com/Articles/2584/AdvComboBox-Version-2-1
Check the OnPaint of the CAdvComboBox class - there is a full implementation of the control repainting including xp theme related issues.
Not sure if it's the same situation - but when I faced this problem (in my case with subclassed CButtons), solving it only required changing the control declaration to a pointer and creating the control dynamically.
Let's assume that your subclassed control is called CComboBoxExt.
Where you had
CComboBoxExt m_cComboBoxExt;
You'll now have
CComboBoxExt* m_pcComboBoxExt;
And on the OnInitDialog of the window where the control is placed, you create it using
m_pcComboBoxExt = new CComboBoxExt();
m_pcComboBoxExt->Create(...)
Since this is now a pointer, don't forget to call DestroyWindow() and delete the pointer on termination.
This solved my particular problem - if your control is declared in the same way, consider giving it a try.
We've created a new, quite complex, WPF application from the ground up and have run into a performance problem as the number of commands registered with the CommandManager increase. We're using simple lightweight commands in our MVVM implementation, however the third party controls we're using (Infragistics) do not, and call CommandManager.RegisterClassCommandBinding liberally to add RoutedCommands. The performance problem manifests itself as a perceived sluggishness in the UI when responding to user input, for example tabbing between controls is slow, text input is 'jerky' and popup animation is 'clunky'. When the app is first fired up the UI is snappy. As more screens containing Infragistics grids are opened the performance deteriorates.
Internally, the CommandManager has a private field named _requerySuggestedHandlers, which is a List< WeakReference>. I've used reflection to get a reference to this collection, and I've noticed that when I call .Clear(), the responsiveness of the UI improves back to its initial state. Obviously I don't want to go round clearing collections that I know little about, especially using reflection (!) but I did it to see if it would cure the performance problems, and voila it did.
Normally, this situation would clean itself up after a certain amount of time passes. However, the collection of WeakReferences (_requerySuggestedHandlers) will only get trimmed once a garbage collection is initiated, which is non-deterministic. Because of this, when we close down windows containing grids (Infragistics XamDataGrid), the CanExecute property for 'dead' grid commands continue to be evaluated unnecessarily, long after the window is closed. This also means that if we close down a number of windows, the performance is still sluggish until a garbage collect is initiated. I understand that this can happen on allocation, and I've seen that myself because if I open a further window this causes the initial memory (from the disposed Windows) to be collected and performance returns to normal.
So, given the above, here are my questions:
How, and from where, does CommandManager.InvalidateRequerySuggested() get called? I haven't found any documentation on MSDN that explains this in any great detail. I hooked up to the CommandManager.RequerySuggested event and it looks like it's being called whenever controls lose focus.
Is is possible to suppress CommandManager.InvalidateRequerySuggested() being called in response to user input?
Has anyone else run into this issue, and if so, how have you avoided it?
Thanks!
This sounds like one of the rare cases where deterministically calling GC.Collect() is the right thing to do. The ordinary argument against it is that the garbage collector is smarter than you are. But when you're dealing with WeakReference objects, you enter territory where you may know something that the garbage collector doesn't. Kicking off garbage collection is certainly better than clearing _requerySuggestedHandlers - among other things, it won't do anything to the WeakReference objects that point to controls that are still alive.
I'd choose this over trying to figure out how to suppress RequerySuggested, since that would screw up the behavior of those commands that you still care about.
What's the easiest way to modify a Winforms track bar so that when a user clicks on it the track bar jumps to the location of the mouse?
By default the track bar moves to half way between it's current location and where the mouse was clicked.
Update: I'm trying to do this so that I can use the track bar on a touch-screen. With a touch-screen dragging is really hard, hence the requirement for the track bar to jump straight to where the user taps.
I've never done it, but I would start by looking at the location of the mouse click. I could then figure out how far across the current extent of the trackbar the click was located and set the tracker's location to that spot.
I'd start by looking into overriding the control and manipulating the Mouse-related event functions (OnMouseDown(), e.g.). Note that in some cases it may be important to call the base class' implementation of an overridden function, be sure to consider it on a case-by-case basis. (I just ran afoul of this, so it's fresh in my mind.)
Note that you should only change the behavior of standard controls in this manner if you have a very compelling reason. They're standard because they behave in a predictable way across many hundreds/thousands of programs. Making something behave differently for just your program can violate the Principle of Lease Astonishment. The only trackbar I can think of that I expect to behave the way you describe is for some sort of media player.
Edit:
Based on your comment, yeah, I think you've got a compelling reason. :)
Background: I have a little video playing app with a UI inspired by the venerable Sasami2k, just updated to use VMR9 (i.e. Direct3D9 with DirectShow) and be less unstable. Currently, it's a C++ app using raw Win32, through necessity: none of the various toolkits are worth a damn. WPF, in particular, was not possible, due to its airspace restrictions.
OK, so, now that D3DImage exists it might be viable to mix and match D3D/VMR9/DirectShow and WPF. Given past frustrations with Win32's inextensibility, this seems like a good thing.
But y'know, I'm falling at the first hurdle here.
With Win32 I have created (very easily) a borderless window that's resizable, resizes proportionately, snaps to the screen edges, and takes up the whole screen (including taskbar area) when maximized. It's a video app, so these are all pretty desirable properties.
OK, so, how to do the same with WPF?
In Win32, I use:
WM_GETMINMAXINFO to control the maximize behaviour
WM_NCHITTEST to control the resize borders
WM_MOVING to control the snap-to-screen-edges
WM_SIZING to control the resize aspect ratio
However, looking at WPF it seems that the various events arrive too late, unless I'm misunderstanding the documentation?
For example, I don't know when I'm mid-move, as LocationChanged says it fires only once the window has moved (which is too late).
Similarly, it appears that StateChanged only fires once the window has been restored/maximized (when I need the information prior to the maximize, to tell the system the correct maximize size).
And I seem to be completely overlooking where the system tells me about resizes. Likewise the hit testing.
So, uh, am I missing something here, or do I have no choice but to drop back to hooking the wndproc of this thing anyway? Can I do what I want without hooking the WndProc?
If I have to use the WndProc I might as well stick with my existing codebase; I want to have simpler, cleaner UI code, and moving away from the WndProc is fundamental to this.
If I do have to hook the WndProc, I have to wonder--why? Win32 has got the sizing/sized, moving/moved, poschanging/poschanged window messages, and they're all useful. Why wouldn't WPF replicate the same set of events? It seems like an unnecessary gap in functionality.
Plus, it means that WPF is tied to a specific USER32-dependent implementation. This means that MS can't (in Windows 7 or 8, say) invert the display layer to make WPF "native" and emulate HWNDs and WndProcs for legacy apps--even though this is precisely what MS should be doing.
OK, to answer my own question, I was missing Adorners (never came back in any of the searches I did, so it doesn't seem that they're as widely known as they perhaps should be).
They seem rather more complex than the WndProc overrides, unfortunately, but I think it should be possible to manhandle them into doing what I want.
And I seem to be completely overlooking where the system tells me about resizes. Likewise the hit testing.
For the resizing you're indeed missing the SizeChanged event.
AFAIK there is sadly no OnSizeChanging, OnLocationChanging and OnStateChanging event on a Window in .NET
I saw that one, but as far as I can tell it only fires after the size has changed, whereas I need the event to fire during the resize. Unless I'm misreading the docs and it
actually fires continuously?
It does not fire continuously but you can probably use the ResizeBegin and ResizeEnd events and be able to do that.
Aren't they WinForms events?
Hmm, you're right.
In code you can set the WindowStyle property to "None" and WindowsState to "Maximized"
Im not sure what the Xaml would look like.
Can you perhaps override the ArrangeOverride and/or MeasureOverride to make up for those missing resize events? Measure is the first pass, and occurs when a layout needs to adjust for a new size, so it's kind of like a size changing event.