📄 fl_x.cxx
字号:
// 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, _motif_wm_hints, _motif_wm_hints, 32, 0, (unsigned char *) prop, 5);#endif}voidFl_Window::size_range_ (){ size_range_set = 1; if (shown ()) i->sendxjunk ();}////////////////////////////////////////////////////////////////// returns pointer to the filename, or null if name ends with '/'const char *filename_name (const char *name){ const char *p, *q; for (p = q = name; *p;) if (*p++ == '/') q = p; return q;}voidFl_Window::label (const char *name, const char *iname){ Fl_Widget::label (name); iconlabel_ = iname; if (shown () && !parent ()) { if (!name) name = "";//tanghao XChangeProperty(fl_display, i->xid, XA_WM_NAME,//tanghao XA_STRING, 8, 0, (uchar*)name, strlen(name)); if (!iname) iname = filename_name (name);//tanghao XChangeProperty(fl_display, i->xid, XA_WM_ICON_NAME, //tanghao 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.C://// 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 intcan_boxcheat (uchar b){ return (b == 1 || (b & 2) && b <= 15);}voidFl_Window::show (){ if (!shown ()) { fl_open_display (); if (can_boxcheat (box ())) fl_background_pixel = int (fl_xpixel (color ())); Fl_X::make_xid (this); } else { //tanghao XMapRaised(fl_display, i->xid); GrRaiseWindow (i->xid); }}Window fl_window;//Gr_WindowFl_Window * Fl_Window::current_;GC fl_gc;// make X drawing go into this window (called by subclass flush() impl.)voidFl_Window::make_current (){ static GC gc; // the GC used by all X windows#ifdef NANO_X if (!gc) gc = GrNewGC ();#else if (!gc) gc = XCreateGC (fl_display, i->xid, 0, 0);#endif fl_window = i->xid; fl_gc = gc; current_ = this; fl_clip_region (0);}//for Normal X,by tanghao#else//#include <config.h>//#include <FL/Fl.H>#include <FL/x.H>#include <FL/Fl_Window.H>#include <ctype.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/time.h>#define CONSOLIDATE_MOTION 1/**** Define this if your keyboard lacks a backspace key... ****//* #define BACKSPACE_HACK 1 */////////////////////////////////////////////////////////////////// interface to poll/select call:#if HAVE_POLL#include <poll.h>static pollfd *pollfds = 0;#else#if HAVE_SYS_SELECT_H# include <sys/select.h>#endif /* HAVE_SYS_SELECT_H */// The following #define is only needed for HP-UX 9.x and earlier://#define select(a,b,c,d,e) select((a),(int *)(b),(int *)(c),(int *)(d),(e))static fd_set fdsets[3];static int maxfd;#define POLLIN 1#define POLLOUT 4#define POLLERR 8#endif /* HAVE_POLL */static int nfds = 0;static int fd_array_size = 0;static struct FD{ int fd; short events; void (*cb) (int, void *); void *arg;} *fd = 0;voidFl::add_fd (int n, int events, void (*cb) (int, void *), void *v){ remove_fd (n, events); int i = nfds++; if (i >= fd_array_size) { fd_array_size = 2 * fd_array_size + 1; fd = (FD *) realloc (fd, fd_array_size * sizeof (FD));#if HAVE_POLL pollfds = (pollfd *) realloc (pollfds, fd_array_size * sizeof (pollfd));#endif } fd[i].fd = n; fd[i].events = events; fd[i].cb = cb; fd[i].arg = v;#if HAVE_POLL fds[i].fd = n; fds[i].events = events;#else if (events & POLLIN) FD_SET (n, &fdsets[0]); if (events & POLLOUT) FD_SET (n, &fdsets[1]); if (events & POLLERR) FD_SET (n, &fdsets[2]); if (n > maxfd) maxfd = n;#endif}voidFl::add_fd (int fd, void (*cb) (int, void *), void *v){ Fl::add_fd (fd, POLLIN, cb, v);}voidFl::remove_fd (int n, int events){ int i, j; for (i = j = 0; i < nfds; i++) { if (fd[i].fd == n) { int e = fd[i].events & ~events; if (!e) continue; // if no events left, delete this fd fd[i].events = e;#if HAVE_POLL fds[j].events = e;#endif } // move it down in the array if necessary: if (j < i) { fd[j] = fd[i];#if HAVE_POLL fds[j] = fds[i];#endif } j++; } nfds = j;#if !HAVE_POLL if (events & POLLIN) FD_CLR (n, &fdsets[0]); if (events & POLLOUT) FD_CLR (n, &fdsets[1]); if (events & POLLERR) FD_CLR (n, &fdsets[2]); if (n == maxfd) maxfd--;#endif}voidFl::remove_fd (int n){ remove_fd (n, -1);}intfl_ready (){ if (XQLength (fl_display)) return 1;#if HAVE_POLL return::poll (fds, nfds, 0);#else timeval t; t.tv_sec = 0; t.tv_usec = 0; fd_set fdt[3]; fdt[0] = fdsets[0]; fdt[1] = fdsets[1]; fdt[2] = fdsets[2]; return::select (maxfd + 1, &fdt[0], &fdt[1], &fdt[2], &t);#endif}#if CONSOLIDATE_MOTIONstatic Fl_Window *send_motion;extern Fl_Window *fl_xmousewin;#endifstatic voiddo_queued_events (){ while (XEventsQueued (fl_display, QueuedAfterReading)) { XEvent xevent; XNextEvent (fl_display, &xevent); fl_handle (xevent); }#if CONSOLIDATE_MOTION if (send_motion && send_motion == fl_xmousewin) { send_motion = 0; Fl::handle (FL_MOVE, fl_xmousewin); }#endif}doublefl_wait (int timeout_flag, double time){ // OpenGL and other broken libraries call XEventsQueued // unnecessarily and thus cause the file descriptor to not be ready, // so we must check for already-read events: if (XQLength (fl_display)) { do_queued_events (); return time; }#if !HAVE_POLL fd_set fdt[3]; fdt[0] = fdsets[0]; fdt[1] = fdsets[1]; fdt[2] = fdsets[2];#endif int n; if (!timeout_flag) {#if HAVE_POLL n =::poll (fds, nfds, -1);#else n =::select (maxfd + 1, &fdt[0], &fdt[1], &fdt[2], 0);#endif } else {#if HAVE_POLL int n =::poll (fds, nfds, time > 0.0 ? int (time * 1000) : 0);#else timeval t; if (time <= 0.0) { t.tv_sec = 0; t.tv_usec = 0; } else { t.tv_sec = int (time); t.tv_usec = int (1000000 * (time - t.tv_sec)); } n =::select (maxfd + 1, &fdt[0], &fdt[1], &fdt[2], &t);#endif } if (n > 0) { for (int i = 0; i < nfds; i++) {#if HAVE_POLL if (fds[i].revents) fd[i].cb (fd[i].fd, fd[i].arg);#else int f = fd[i].fd; short revents = 0; if (FD_ISSET (f, &fdt[0])) revents |= POLLIN; if (FD_ISSET (f, &fdt[1])) revents |= POLLOUT; if (FD_ISSET (f, &fdt[2])) revents |= POLLERR; if (fd[i].events & revents) fd[i].cb (f, fd[i].arg);#endif } } return time;}////////////////////////////////////////////////////////////////Display *fl_display;int fl_screen;XVisualInfo *fl_visual;Colormap fl_colormap;static Atom wm_delete_window;static Atom wm_protocols;static Atom _motif_wm_hints;static voidfd_callback (int, void *){ do_queued_events ();}static intio_error_handler (Display *){ Fl::fatal ("X I/O error"); return 0;}static intxerror_handler (Display * d, XErrorEvent * e){ char buf1[128], buf2[128]; sprintf (buf1, "XRequest.%d", e->request_code); XGetErrorDatabaseText (d, "", buf1, buf1, buf2, 128); XGetErrorText (d, e->error_code, buf1, 128); Fl::warning ("%s: %s 0x%lx", buf2, buf1, e->resourceid); return 0;}voidfl_open_display (){ if (fl_display) return; XSetIOErrorHandler (io_error_handler); XSetErrorHandler (xerror_handler); Display *d = XOpenDisplay (0); if (!d) Fl::fatal ("Can't open display: %s", XDisplayName (0)); fl_display = d; wm_delete_window = XInternAtom (d, "WM_DELETE_WINDOW", 0); wm_protocols = XInternAtom (d, "WM_PROTOCOLS", 0); _motif_wm_hints = XInternAtom (d, "_MOTIF_WM_HINTS", 0); Fl::add_fd (ConnectionNumber (d), POLLIN, fd_callback); fl_screen = DefaultScreen (fl_display);// construct an XVisualInfo that matches the default Visual: XVisualInfo templt; int num; templt.visualid = XVisualIDFromVisual (DefaultVisual (fl_display, fl_screen)); fl_visual = XGetVisualInfo (fl_display, VisualIDMask, &templt, &num); fl_colormap = DefaultColormap (fl_display, fl_screen);}voidfl_close_display (){ Fl::remove_fd (ConnectionNumber (fl_display)); XCloseDisplay (fl_display);}intFl::h (){ fl_open_display (); return DisplayHeight (fl_display, fl_screen);}intFl::w (){ fl_open_display (); return DisplayWidth (fl_display, fl_screen);}voidFl::get_mouse (int &x, int &y){ fl_open_display (); Window root = RootWindow (fl_display, fl_screen); Window c; int mx, my, cx, cy; unsigned int mask; XQueryPointer (fl_display, root, &root, &c, &mx, &my, &cx, &cy, &mask); x = mx; y = my;}////////////////////////////////////////////////////////////////const XEvent *fl_xevent; // the current x eventulong fl_event_time; // the last timestamp from an x eventchar fl_key_vector[32]; // used by Fl::get_key()// Record event mouse position and state from an XEvent:static int px, py;static ulong ptime;static voidset_event_xy (){#if CONSOLIDATE_MOTION send_motion = 0;#endif Fl::e_x_root = fl_xevent->xbutton.x_root; Fl::e_x = fl_xevent->xbutton.x; Fl::e_y_root = fl_xevent->xbutton.y_root; Fl::e_y = fl_xevent->xbutton.y; Fl::e_state = fl_xevent->xbutton.state << 16; fl_event_time = fl_xevent->xbutton.time;#ifdef __sgi // get the meta key off PC keyboards: if (fl_key_vector[18] & 0x18) Fl::e_state |= FL_META;#endif // turn off is_click if enough time or mouse movement has passed: if (abs (Fl::e_x_root - px) + abs (Fl::e_y_root - py) > 3 || fl_event_time >= ptime + 1000) Fl::e_is_click = 0;}// if this is same event as last && is_click, increment click count:static inline voidcheckdouble (){ if (Fl::e_is_click == Fl::e_keysym) Fl::e_clicks++; else { Fl::e_clicks = 0; Fl::e_is_click = Fl::e_keysym; } px = Fl::e_x_root; py = Fl::e_y_root; ptime = fl_event_time;}static Fl_Window *resize_bug_fix;////////////////////////////////////////////////////////////////intfl_handle (const XEvent & xevent){ fl_xevent = &xevent; Window xid = xevent.xany.window; switch (xevent.type) { // events where we don't care about window: case KeymapNotify: memcpy (fl_key_vector, xevent.xkeymap.key_vector, 32); return 0; case MappingNotify: XRefreshKeyboardMapping ((XMappingEvent *) & xevent.xmapping); return 0; // events where interesting window id is in a different place: case CirculateNotify: case CirculateRequest: case ConfigureNotify: case ConfigureRequest: case CreateNotify: case DestroyNotify: case GravityNotify: case MapNotify: case MapRequest: case ReparentNotify: case UnmapNotify: xid = xevent.xmaprequest.window; break; } int event = 0; Fl_Window *window = fl_find (xid); if (window) switch (xevent.type) { case ClientMessage: if ((Atom) (xevent.xclient.data.l[0]) == wm_delete_window) event = FL_CLOSE; break; case MapNotify: event = FL_SHOW;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -