tags:

views:

34

answers:

2

i'm writing some low level window code for a window in x (in c++), and I want to prevent the user from either maximising or minimising the window. i don't mind whether this is done by rejecting the request to resize, or by removing the buttons themselves. however, i am tied to x and can't use qt or other higher-level libraries which i know provide this functionality.

at the moment all i have managed to do is intercept the ResizeRequest event and then set the window size back using XResizeWindow... but this causes the window to momentarily maximise and then return to its original state. is there a way to directly reject a ResizeRequest, that would seem to be the proper way to handle this but a fair bit of googling and document trawling has not come up with a solution.

thanks, james

A: 

you can't.

essentially you would fight like hell against the window manager (and against the user in the end). eg, you could watch PropertyNotify events to check if your window (or rather the window your window is attached to (provided by the window manager)) gets minimized. and then you unminimize it. and then the user minimizes it, or the window manager. technically, you can fight against it, but i would strongly advise against it.

that said: you can try to give the window manager some hints about what you think is appropriate for the window. see http://standards.freedesktop.org/wm-spec/1.3/ar01s05.html#id2523223:

_NET_WM_ALLOWED_ACTIONS

is a property the window manager manages per window (to tell other tools what is possible with that window). one of such actions is

_NET_WM_ACTION_RESIZE indicates that the window may be resized. 
(Implementation note: Window Managers can identify a non-resizable
window because its minimum and maximum size in WM_NORMAL_HINTS will 
be the same.)

so, if your users are using a window manager which interpretes WM_NORMAL_HINTS correctly and drops any resizing, maximizing, minimizing: then you can feel lucky.

what do you really want to achieve? some kind of kiosk-mode? some kind of fair-trade mode where people walking by can not "shutdown", close, resize, fiddle around with the app you are presenting?

if so: consider running a xsession without any window manager involved at all. just start your app as big as you need it and done.

akira
i want to create a non-resizable window. surely this is possible, higher-level managers achieve this. for example in java you can set a window as non-resizable and it disables the maximize/minimize buttons.
james edge
@james But why do you want a non-resizable window. Is something going to break if the window is resized, or are you just imposing your ideas on your user. What if the user changes the font size of the stuff in the window? What if there is some message in the window that is longer than you expected. Unless there is a good reason, don't take capabilities away from the user.
KeithB
just because there are no "buttons" does not mean anything. alt+leftmouse in most window managers and off you go. you could set some size hints (man XSizeHints) and a compliant window manager will respect these "hints".
akira
keith, it isn't a main window... its a window being launched from within a plugin to another application. i'm using opengl to render some intermediate results to the window (no text). in terms of the application it doesn't make sense for the window to be resizable. the XSizeHints suggestion is probably the way to go. i'm just a little surprised there isn't a more direct route of doing this.
james edge
the term for such windows is "transient windows", read http://tronche.com/gui/x/icccm/sec-4.html#WM_TRANSIENT_FOR and http://tronche.com/gui/x/xlib/ICC/client-to-window-manager/XSetTransientForHint.html
akira
+1  A: 

Technically you can't prevent anything, as WMs can do whatever they want, but most reasonable window managers will let you control this.

The preferred modern way to do it is to set _NET_WM_WINDOW_TYPE semantic type if any of those are applicable. For example, in many WMs a dialog type may imply not-maximizable. http://standards.freedesktop.org/wm-spec/1.3/

It sounds like none of these apply to your app though probably, so you'll have to set the specific hints.

To avoid maximization you just want to make the window not-resizable. As you've discovered, "fighting" the resize by just resizing back is a Bad Idea. It has infinite loop potential among other things.

XSetWMSizeHints() is the correct way to avoid maximization. Set min size = max size. voila, not resizable.

To avoid minimization, you have to use a bit of old legacy cruft called the Mwm hints. Unfortunately this involves cut-and-pasting a struct definition and then setting a property to the bits of the struct.

I just googled for MWM hints docs, and one of the results is me suggesting documenting them, 9 years ago ;-) http://mail.gnome.org/archives/wm-spec-list/2001-December/msg00044.html Unfortunately, none of the results are actual docs.

You can likely figure it out from http://git.gnome.org/browse/gtk+/tree/gdk/x11/MwmUtil.h and gdk_window_set_mwm_hints() http://git.gnome.org/browse/gtk+/tree/gdk/x11/gdkwindow-x11.c#n4389

MwmUtil.h is the struct that's cut-and-pasted everywhere (into most WMs and toolkits).

The _NET_WM_ALLOWED_ACTIONS hint is set on your window by the WM indicating which features the WM has decided to put on the window. The main purpose of this hint is that pagers and task lists and other desktop components can then offer the matching actions for the window.

The specs that cover all this are the ICCCM (old spec, still mostly valid) and EMWH (new extensions and clarifications, since ICCCM left lots of things unaddressed).

For gory details, try the source code... for example recalc_window_features() in metacity's window.c file, currently on line 6185 http://git.gnome.org/browse/metacity/tree/src/core/window.c#n6185

A philosophical adjustment when coding for X: mileage will vary with window manager. The "mainstream" ones lots of people use generally will follow the specs and work about as you'd expect. However, there are all kinds of WMs out there, some broken, others deliberately quirky. The worst thing you can do is try to "fight" or work around the WM, because basically all ways of doing that will end up breaking the app when running with a sane WM. Your best bet is make things follow the specs, work with the normal WMs, and if you get users upset that they can resize your not-resizable window because their WM allows that, you just have to tell them to complain to whoever provides that WM. The whole point of the pluggable WM design is that the WM determines some of this behavior, rather than the app.

Good luck. Modern X is pretty complex and coding Xlib with no toolkit is kind of asking for things to be... not quite right. But you can probably get it going well enough. :-P

Havoc P