fl_x.cxx
来自「SRI international 发布的OAA框架软件」· CXX 代码 · 共 1,259 行 · 第 1/3 页
CXX
1,259 行
return 0;
# else
event = FL_MOVE;
fl_xmousewin = window;
break;
# endif
case ButtonRelease:
Fl::e_keysym = FL_Button + xevent.xbutton.button;
set_event_xy();
Fl::e_state &= ~(FL_BUTTON1 << (xevent.xbutton.button-1));
if (xevent.xbutton.button == Button4 ||
xevent.xbutton.button == Button5) return 0;
event = FL_RELEASE;
fl_xmousewin = window;
break;
case EnterNotify:
if (xevent.xcrossing.detail == NotifyInferior) break;
// XInstallColormap(fl_display, Fl_X::i(window)->colormap);
set_event_xy();
Fl::e_state = xevent.xcrossing.state << 16;
event = FL_ENTER;
fl_xmousewin = window;
break;
case LeaveNotify:
if (xevent.xcrossing.detail == NotifyInferior) break;
set_event_xy();
Fl::e_state = xevent.xcrossing.state << 16;
// event = FL_LEAVE;
fl_xmousewin = 0;
break;
// We cannot rely on the x,y position in the configure notify event.
// I now think this is an unavoidable problem with X: it is impossible
// for a window manager to prevent the "real" notify event from being
// sent when it resizes the contents, even though it can send an
// artificial event with the correct position afterwards (and some
// window managers do not send this fake event anyway)
// So anyway, do a round trip to find the correct x,y:
case MapNotify:
event = FL_SHOW;
case ConfigureNotify: {
if (window->parent()) break; // ignore child windows
// figure out where OS really put window
XWindowAttributes actual;
XGetWindowAttributes(fl_display, fl_xid(window), &actual);
Window cr; int X, Y, W = actual.width, H = actual.height;
XTranslateCoordinates(fl_display, fl_xid(window), actual.root,
0, 0, &X, &Y, &cr);
// tell Fl_Window about it and set flag to prevent echoing:
resize_bug_fix = window;
window->resize(X, Y, W, H);
break; // allow add_handler to do something too
}
}
return Fl::handle(event, window);
}
////////////////////////////////////////////////////////////////
void Fl_Window::resize(int X,int Y,int W,int H) {
int is_a_resize = (W != w() || H != h());
int resize_from_program = (this != resize_bug_fix);
if (!resize_from_program) resize_bug_fix = 0;
if (X != x() || Y != y()) set_flag(FL_FORCE_POSITION);
else if (!is_a_resize) return;
if (is_a_resize) {
Fl_Group::resize(X,Y,W,H);
if (shown()) {redraw(); i->wait_for_expose = 1;}
} else {
x(X); y(Y);
}
if (resize_from_program && shown()) {
if (is_a_resize) {
if (!resizable()) size_range(w(),h(),w(),h());
XMoveResizeWindow(fl_display, i->xid, X, Y, W>0 ? W : 1, H>0 ? H : 1);
} else
XMoveWindow(fl_display, i->xid, X, Y);
}
}
////////////////////////////////////////////////////////////////
// A subclass of Fl_Window may call this to associate an X window it
// creates with the Fl_Window:
void fl_fix_focus(); // in Fl.cxx
Fl_X* Fl_X::set_xid(Fl_Window* win, Window winxid) {
Fl_X* xp = new Fl_X;
xp->xid = winxid;
xp->other_xid = 0;
xp->setwindow(win);
xp->next = Fl_X::first;
xp->region = 0;
xp->wait_for_expose = 1;
xp->backbuffer_bad = 1;
Fl_X::first = xp;
if (win->modal()) {Fl::modal_ = win; fl_fix_focus();}
return xp;
}
// More commonly a subclass calls this, because it hides the really
// ugly parts of X and sets all the stuff for a window that is set
// normally. The global variables like fl_show_iconic are so that
// subclasses of *that* class may change the behavior...
char fl_show_iconic; // hack for iconize()
int fl_background_pixel = -1; // hack to speed up bg box drawing
int fl_disable_transient_for; // secret method of removing TRANSIENT_FOR
static const int childEventMask = ExposureMask;
static const int XEventMask =
ExposureMask|StructureNotifyMask
|KeyPressMask|KeyReleaseMask|KeymapStateMask|FocusChangeMask
|ButtonPressMask|ButtonReleaseMask
|EnterWindowMask|LeaveWindowMask
|PointerMotionMask;
void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap)
{
Fl_Group::current(0); // get rid of very common user bug: forgot end()
int X = win->x();
int Y = win->y();
int W = win->w();
if (W <= 0) W = 1; // X don't like zero...
int H = win->h();
if (H <= 0) H = 1; // X don't like zero...
if (!win->parent() && !Fl::grab()) {
// center windows in case window manager does not do anything:
if (!(win->flags() & Fl_Window::FL_FORCE_POSITION)) {
win->x(X = (Fl::w()-W)/2);
win->y(Y = (Fl::h()-H)/2);
}
// force the window to be on-screen. Usually the X window manager
// does this, but a few don't, so we do it here for consistency:
if (win->border()) {
// ensure border is on screen:
// (assumme extremely minimal dimensions for this border)
const int top = 20;
const int left = 1;
const int right = 1;
const int bottom = 1;
if (X+W+right > Fl::w()) X = Fl::w()-right-W;
if (X-left < 0) X = left;
if (Y+H+bottom > Fl::h()) Y = Fl::h()-bottom-H;
if (Y-top < 0) Y = top;
}
// now insure contents are on-screen (more important than border):
if (X+W > Fl::w()) X = Fl::w()-W;
if (X < 0) X = 0;
if (Y+H > Fl::h()) Y = Fl::h()-H;
if (Y < 0) Y = 0;
}
ulong root = win->parent() ?
fl_xid(win->window()) : RootWindow(fl_display, fl_screen);
XSetWindowAttributes attr;
int mask = CWBorderPixel|CWColormap|CWEventMask|CWBitGravity;
attr.event_mask = win->parent() ? childEventMask : XEventMask;
attr.colormap = colormap;
attr.border_pixel = 0;
attr.bit_gravity = 0; // StaticGravity;
if (win->override()) {
attr.override_redirect = 1;
attr.save_under = 1;
mask |= CWOverrideRedirect | CWSaveUnder;
} else attr.override_redirect = 0;
if (Fl::grab()) {
attr.save_under = 1; mask |= CWSaveUnder;
if (!win->border()) {attr.override_redirect = 1; mask |= CWOverrideRedirect;}
}
if (fl_background_pixel >= 0) {
attr.background_pixel = fl_background_pixel;
fl_background_pixel = -1;
mask |= CWBackPixel;
}
Fl_X* xp =
set_xid(win, XCreateWindow(fl_display,
root,
X, Y, W, H,
0, // borderwidth
visual->depth,
InputOutput,
visual->visual,
mask, &attr));
int showit = 1;
if (!win->parent() && !attr.override_redirect) {
// Communicate all kinds 'o junk to the X Window Manager:
win->label(win->label(), win->iconlabel());
XChangeProperty(fl_display, xp->xid, WM_PROTOCOLS,
XA_ATOM, 32, 0, (uchar*)&WM_DELETE_WINDOW, 1);
// send size limits and border:
xp->sendxjunk();
// set the class property, which controls the icon used:
if (win->xclass()) {
char buffer[1024];
char *p; const char *q;
// truncate on any punctuation, because they break XResource lookup:
for (p = buffer, q = win->xclass(); isalnum(*q)||(*q&128);) *p++ = *q++;
*p++ = 0;
// create the capitalized version:
q = buffer;
*p = toupper(*q++); if (*p++ == 'X') *p++ = toupper(*q++);
while ((*p++ = *q++));
XChangeProperty(fl_display, xp->xid, XA_WM_CLASS, XA_STRING, 8, 0,
(unsigned char *)buffer, p-buffer-1);
}
if (win->non_modal() && xp->next && !fl_disable_transient_for) {
// find some other window to be "transient for":
Fl_Window* wp = xp->next->w;
while (wp->parent()) wp = wp->window();
XSetTransientForHint(fl_display, xp->xid, fl_xid(wp));
if (!wp->visible()) showit = 0; // guess that wm will not show it
}
// Make it receptive to DnD:
int version = 4;
XChangeProperty(fl_display, xp->xid, fl_XdndAware,
XA_ATOM, sizeof(int)*8, 0, (unsigned char*)&version, 1);
XWMHints hints;
hints.input = True;
hints.flags = InputHint;
if (fl_show_iconic) {
hints.flags |= StateHint;
hints.initial_state = IconicState;
fl_show_iconic = 0;
showit = 0;
}
if (win->icon()) {
hints.icon_pixmap = (Pixmap)win->icon();
hints.flags |= IconPixmapHint;
}
XSetWMHints(fl_display, xp->xid, &hints);
}
XMapWindow(fl_display, xp->xid);
if (showit) {
win->set_visible();
win->handle(FL_SHOW); // get child windows to appear
win->redraw();
}
}
////////////////////////////////////////////////////////////////
// Send X window stuff that can be changed over time:
void Fl_X::sendxjunk() {
if (w->parent() || w->override()) return; // it's not a window manager window!
if (!w->size_range_set) { // default size_range based on resizable():
if (w->resizable()) {
Fl_Widget *o = w->resizable();
int minw = o->w(); if (minw > 100) minw = 100;
int minh = o->h(); if (minh > 100) minh = 100;
w->size_range(w->w() - o->w() + minw, w->h() - o->h() + minh, 0, 0);
} else {
w->size_range(w->w(), w->h(), w->w(), w->h());
}
return; // because this recursively called here
}
XSizeHints hints;
// memset(&hints, 0, sizeof(hints)); jreiser suggestion to fix purify?
hints.min_width = w->minw;
hints.min_height = w->minh;
hints.max_width = w->maxw;
hints.max_height = w->maxh;
hints.width_inc = w->dw;
hints.height_inc = w->dh;
hints.win_gravity = StaticGravity;
// see the file /usr/include/X11/Xm/MwmUtil.h:
// fill all fields to avoid bugs in kwm and perhaps other window managers:
// 0, MWM_FUNC_ALL, MWM_DECOR_ALL
long prop[5] = {0, 1, 1, 0, 0};
if (hints.min_width != hints.max_width ||
hints.min_height != hints.max_height) { // resizable
hints.flags = PMinSize|PWinGravity;
if (hints.max_width >= hints.min_width ||
hints.max_height >= hints.min_height) {
hints.flags = PMinSize|PMaxSize|PWinGravity;
// unfortunately we can't set just one maximum size. Guess a
// value for the other one. Some window managers will make the
// window fit on screen when maximized, others will put it off screen:
if (hints.max_width < hints.min_width) hints.max_width = Fl::w();
if (hints.max_height < hints.min_height) hints.max_height = Fl::h();
}
if (hints.width_inc && hints.height_inc) hints.flags |= PResizeInc;
if (w->aspect) {
// stupid X! It could insist that the corner go on the
// straight line between min and max...
hints.min_aspect.x = hints.max_aspect.x = hints.min_width;
hints.min_aspect.y = hints.max_aspect.y = hints.min_height;
hints.flags |= PAspect;
}
} else { // not resizable:
hints.flags = PMinSize|PMaxSize|PWinGravity;
prop[0] = 1; // MWM_HINTS_FUNCTIONS
prop[1] = 1|2|16; // MWM_FUNC_ALL | MWM_FUNC_RESIZE | MWM_FUNC_MAXIMIZE
}
if (w->flags() & Fl_Window::FL_FORCE_POSITION) {
hints.flags |= USPosition;
hints.x = w->x();
hints.y = w->y();
}
if (!w->border()) {
prop[0] |= 2; // MWM_HINTS_DECORATIONS
prop[2] = 0; // no decorations
}
XSetWMNormalHints(fl_display, xid, &hints);
XChangeProperty(fl_display, xid,
fl_MOTIF_WM_HINTS, fl_MOTIF_WM_HINTS,
32, 0, (unsigned char *)prop, 5);
}
void Fl_Window::size_range_() {
size_range_set = 1;
if (shown()) i->sendxjunk();
}
////////////////////////////////////////////////////////////////
// returns pointer to the filename, or null if name ends with '/'
const char *fl_filename_name(const char *name) {
const char *p,*q;
if (!name) return (0);
for (p=q=name; *p;) if (*p++ == '/') q = p;
return q;
}
void Fl_Window::label(const char *name,const char *iname) {
Fl_Widget::label(name);
iconlabel_ = iname;
if (shown() && !parent()) {
if (!name) name = "";
XChangeProperty(fl_display, i->xid, XA_WM_NAME,
XA_STRING, 8, 0, (uchar*)name, strlen(name));
if (!iname) iname = fl_filename_name(name);
XChangeProperty(fl_display, i->xid, XA_WM_ICON_NAME,
XA_STRING, 8, 0, (uchar*)iname, strlen(iname));
}
}
////////////////////////////////////////////////////////////////
// Implement the virtual functions for the base Fl_Window class:
// If the box is a filled rectangle, we can make the redisplay *look*
// faster by using X's background pixel erasing. We can make it
// actually *be* faster by drawing the frame only, this is done by
// setting fl_boxcheat, which is seen by code in fl_drawbox.cxx:
//
// On XFree86 (and prehaps all X's) this has a problem if the window
// is resized while a save-behind window is atop it. The previous
// contents are restored to the area, but this assummes the area
// is cleared to background color. So this is disabled in this version.
// Fl_Window *fl_boxcheat;
static inline int can_boxcheat(uchar b) {return (b==1 || (b&2) && b<=15);}
void Fl_Window::show() {
image(Fl::scheme_bg_);
if (Fl::scheme_bg_) {
labeltype(FL_NORMAL_LABEL);
align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP);
} else {
labeltype(FL_NO_LABEL);
}
if (!shown()) {
fl_open_display();
if (can_boxcheat(box())) fl_background_pixel = int(fl_xpixel(color()));
Fl_X::make_xid(this);
} else {
XMapRaised(fl_display, i->xid);
}
}
Window fl_window;
Fl_Window *Fl_Window::current_;
GC fl_gc;
// make X drawing go into this window (called by subclass flush() impl.)
void Fl_Window::make_current() {
static GC gc; // the GC used by all X windows
if (!gc) gc = XCreateGC(fl_display, i->xid, 0, 0);
fl_window = i->xid;
fl_gc = gc;
current_ = this;
fl_clip_region(0);
}
#endif
//
// End of "$Id: Fl_x.cxx,v 1.1.1.1 2003/06/03 22:25:45 agno Exp $".
//
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?