ede/edewm/Mwm.cpp
2009-02-20 13:05:43 +00:00

192 lines
6.1 KiB
C++

#include "Mwm.h"
#include "Frame.h"
#include "Winhints.h"
#include "Windowmanager.h"
void MWM::get_hints(Frame *f)
{
if(f->mwm_hints) {
XFree((char *)f->mwm_hints);
f->mwm_hints = 0;
}
unsigned long n=0;
f->mwm_hints = (MwmHints *)getProperty(f->window(), _XATOM_MWM_HINTS, _XATOM_MWM_HINTS, &n);
if(n >= PROP_MWM_HINTS_ELEMENTS) {
// Fill in the default value for missing fields:
if(!(f->mwm_hints->flags & MWM_HINTS_FUNCTIONS))
f->mwm_hints->functions = MWM_FUNC_ALL;
if(!(f->mwm_hints->flags & MWM_HINTS_DECORATIONS))
f->mwm_hints->decorations = MWM_DECOR_ALL;
} else {
XFree((char *)f->mwm_hints);
f->mwm_hints = 0;
}
}
static long mwm_functions(MwmHints *hints, XSizeHints *sh)
{
long functions = ~0U;
if(hints && (hints->flags & MWM_HINTS_FUNCTIONS))
{
if(hints->functions & MWM_FUNC_ALL)
functions = ~hints->functions;
else
functions = hints->functions;
} else {
if(sh) {
bool minmax = false;
if(sh->min_width == sh->max_width && sh->min_height == sh->max_height) {
functions &= ~MWM_FUNC_RESIZE;
minmax = true;
}
if((minmax && !(sh->flags & PResizeInc)) ||
(sh->width_inc == 0 && sh->height_inc == 0))
functions &= ~MWM_FUNC_MAXIMIZE;
}
}
functions &= (MWM_FUNC_RESIZE | MWM_FUNC_MOVE |
MWM_FUNC_MINIMIZE | MWM_FUNC_MAXIMIZE |
MWM_FUNC_CLOSE);
return functions;
}
static long mwm_decors(MwmHints *hints, XSizeHints *sh)
{
long decors = ~0U;
long func = mwm_functions(hints, sh);
if(hints && (hints->flags & MWM_HINTS_DECORATIONS)) {
if(hints->decorations & MWM_DECOR_ALL)
decors = ~hints->decorations;
else
decors = hints->decorations;
} else {
if(sh) {
bool minmax = false;
if(sh->min_width == sh->max_width && sh->min_height == sh->max_height) {
decors &= ~MWM_DECOR_RESIZEH;
minmax = true;
}
if((minmax && !(sh->flags & PResizeInc)) ||
(sh->width_inc == 0 && sh->height_inc == 0))
decors &= ~MWM_DECOR_MAXIMIZE;
}
}
decors &= (MWM_DECOR_BORDER | MWM_DECOR_RESIZEH |
MWM_DECOR_TITLE | MWM_DECOR_MENU |
MWM_DECOR_MINIMIZE | MWM_DECOR_MAXIMIZE);
// Add disabled buttons !!!
decors &=
~(/*((func & MWM_FUNC_RESIZE) ? 0 : MWM_DECOR_RESIZEH) |*/
((func & MWM_FUNC_MINIMIZE) ? 0 : MWM_DECOR_MINIMIZE) |
((func & MWM_FUNC_MAXIMIZE) ? 0 : MWM_DECOR_MAXIMIZE));
return decors;
}
bool MWM::update_hints(Frame *f)
{
MwmHints *mwm_hints = f->mwm_hints;
XSizeHints *size_hints = f->size_hints;
long decors = mwm_decors(mwm_hints, size_hints);
long functions = mwm_functions(mwm_hints, size_hints);
bool funcs_only = (mwm_hints &&
(mwm_hints->flags & (MWM_HINTS_FUNCTIONS) == MWM_HINTS_FUNCTIONS) &&
(mwm_hints->flags & (MWM_HINTS_DECORATIONS) != MWM_HINTS_DECORATIONS)
);
// The low bit means "turn the marked items off", invert this.
// Transient windows already have size & iconize buttons turned off:
if(functions & MWM_FUNC_ALL)
functions = ~functions & (f->transient_for_xid ? ~0x58 : -1);
if(decors & MWM_DECOR_ALL)
decors = ~decors & (f->transient_for_xid ? ~0x60 : -1);
int old_decor_flags = f->decor_flags();
int old_func_flags = f->func_flags();
int old_frame_flags = f->frame_flags();
// Get decorations
f->clear_decor_flags();
if(decors & MWM_DECOR_BORDER)
f->set_decor_flag(BORDER);
if(decors & MWM_DECOR_TITLE)
f->set_decor_flag(TITLEBAR);
if(decors & MWM_DECOR_MENU)
f->set_decor_flag(SYSMENU);
if(decors & MWM_DECOR_MINIMIZE)
f->set_decor_flag(MINIMIZE);
if(decors & MWM_DECOR_MAXIMIZE)
f->set_decor_flag(MAXIMIZE);
if(decors & MWM_DECOR_RESIZEH)
f->set_decor_flag(RESIZE);
// Get functions
f->clear_func_flags();
if(functions & MWM_FUNC_RESIZE) {
f->set_func_flag(RESIZE);
if(funcs_only) f->set_decor_flag(RESIZE|BORDER);
}
if(functions & MWM_FUNC_MOVE) {
f->set_func_flag(MOVE);
if(funcs_only) f->set_decor_flag(BORDER);
}
if(functions & MWM_FUNC_MINIMIZE) {
f->set_func_flag(MINIMIZE);
if(funcs_only) f->set_decor_flag(MINIMIZE);
}
if(functions & MWM_FUNC_MAXIMIZE) {
f->set_func_flag(MAXIMIZE);
if(funcs_only) f->set_decor_flag(MAXIMIZE);
}
if(functions & MWM_FUNC_CLOSE) {
f->set_func_flag(CLOSE);
f->set_decor_flag(CLOSE);
}
// some Motif programs use this to disable resize :-(
// and some programs change this after the window is shown (*&%$#%)
if(!(functions & MWM_FUNC_RESIZE) || !(decors & MWM_DECOR_RESIZEH))
f->clear_decor_flag(RESIZE);
else
f->set_decor_flag(RESIZE);
// and some use this to disable the Close function. The commented
// out test is it trying to turn off the mwm menu button: it appears
// programs that do that still expect Alt+F4 to close them, so I
// leave the close on then:
if (!(functions & 0x20) /*|| !(prop[2]&0x10)*/) {
f->clear_func_flag(CLOSE);
f->clear_decor_flag(CLOSE);
} else {
f->set_func_flag(CLOSE);
f->set_decor_flag(CLOSE);
}
// Set modal
if(!f->shown() && mwm_hints && (mwm_hints->flags & MWM_HINTS_INPUT_MODE) && (mwm_hints->input_mode != MWM_INPUT_MODELESS))
f->set_frame_flag(MODAL);
return ((f->frame_flags() ^ old_frame_flags) || (f->decor_flags() ^ old_decor_flags) || (f->func_flags() ^ old_func_flags));
}
void MWM::set_motif_info()
{
MotifWmInfo mwminfo;
mwminfo.flags = MWM_INFO_STARTUP_CUSTOM;
mwminfo.wm_window = root_win;
XChangeProperty(fl_display, root_win, _XATOM_MOTIF_WM_INFO, _XATOM_MOTIF_WM_INFO,
32, PropModeReplace,
(unsigned char *)&mwminfo, 2);
}