fl_x.cxx
来自「SRI international 发布的OAA框架软件」· CXX 代码 · 共 1,259 行 · 第 1/3 页
CXX
1,259 行
//
// "$Id: Fl_x.cxx,v 1.1.1.1 2003/06/03 22:25:45 agno Exp $"
//
// X specific code for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2003 by Bill Spitzak and others.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
//
// Please report all bugs and problems to "fltk-bugs@fltk.org".
//
#ifdef WIN32
# include "Fl_win32.cxx"
#elif defined(__APPLE__)
# include "Fl_mac.cxx"
#else
# define CONSOLIDATE_MOTION 1
/**** Define this if your keyboard lacks a backspace key... ****/
/* #define BACKSPACE_HACK 1 */
# include <FL/Fl.H>
# include <FL/x.H>
# include <FL/Fl_Window.H>
# include <stdio.h>
# include <stdlib.h>
# include "flstring.h"
# include <unistd.h>
# include <sys/time.h>
////////////////////////////////////////////////////////////////
// interface to poll/select call:
# if USE_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 /* USE_POLL */
static int nfds = 0;
static int fd_array_size = 0;
struct FD {
# if !USE_POLL
int fd;
short events;
# endif
void (*cb)(int, void*);
void* arg;
};
static FD *fd = 0;
void Fl::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 *temp;
fd_array_size = 2*fd_array_size+1;
if (!fd) temp = (FD*)malloc(fd_array_size*sizeof(FD));
else temp = (FD*)realloc(fd, fd_array_size*sizeof(FD));
if (!temp) return;
fd = temp;
# if USE_POLL
pollfd *tpoll;
if (!pollfds) tpoll = (pollfd*)malloc(fd_array_size*sizeof(pollfd));
else tpoll = (pollfd*)realloc(pollfds, fd_array_size*sizeof(pollfd));
if (!tpoll) return;
pollfds = tpoll;
# endif
}
fd[i].cb = cb;
fd[i].arg = v;
# if USE_POLL
pollfds[i].fd = n;
pollfds[i].events = events;
# else
fd[i].fd = n;
fd[i].events = events;
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
}
void Fl::add_fd(int n, void (*cb)(int, void*), void* v) {
Fl::add_fd(n, POLLIN, cb, v);
}
void Fl::remove_fd(int n, int events) {
int i,j;
for (i=j=0; i<nfds; i++) {
# if USE_POLL
if (pollfds[i].fd == n) {
int e = pollfds[i].events & ~events;
if (!e) continue; // if no events left, delete this fd
pollfds[j].events = e;
}
# else
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;
}
# endif
// move it down in the array if necessary:
if (j<i) {
fd[j] = fd[i];
# if USE_POLL
pollfds[j] = pollfds[i];
# endif
}
j++;
}
nfds = j;
# if !USE_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
}
void Fl::remove_fd(int n) {
remove_fd(n, -1);
}
# if CONSOLIDATE_MOTION
static Fl_Window* send_motion;
extern Fl_Window* fl_xmousewin;
# endif
static void do_queued_events() {
while (XEventsQueued(fl_display,QueuedAfterReading)) {
XEvent xevent;
XNextEvent(fl_display, &xevent);
fl_handle(xevent);
}
// we send FL_LEAVE only if the mouse did not enter some other window:
if (!fl_xmousewin) Fl::handle(FL_LEAVE, 0);
# if CONSOLIDATE_MOTION
else if (send_motion == fl_xmousewin) {
send_motion = 0;
Fl::handle(FL_MOVE, fl_xmousewin);
}
# endif
}
// these pointers are set by the Fl::lock() function:
static void nothing() {}
void (*fl_lock_function)() = nothing;
void (*fl_unlock_function)() = nothing;
// This is never called with time_to_wait < 0.0:
// It should return negative on error, 0 if nothing happens before
// timeout, and >0 if any callbacks were done.
int fl_wait(double time_to_wait) {
// 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 (fl_display && XQLength(fl_display)) {do_queued_events(); return 1;}
# if !USE_POLL
fd_set fdt[3];
fdt[0] = fdsets[0];
fdt[1] = fdsets[1];
fdt[2] = fdsets[2];
# endif
int n;
fl_unlock_function();
if (time_to_wait < 2147483.648) {
# if USE_POLL
n = ::poll(pollfds, nfds, int(time_to_wait*1000 + .5));
# else
timeval t;
t.tv_sec = int(time_to_wait);
t.tv_usec = int(1000000 * (time_to_wait-t.tv_sec));
n = ::select(maxfd+1,&fdt[0],&fdt[1],&fdt[2],&t);
# endif
} else {
# if USE_POLL
n = ::poll(pollfds, nfds, -1);
# else
n = ::select(maxfd+1,&fdt[0],&fdt[1],&fdt[2],0);
# endif
}
fl_lock_function();
if (n > 0) {
for (int i=0; i<nfds; i++) {
# if USE_POLL
if (pollfds[i].revents) fd[i].cb(pollfds[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 n;
}
// fl_ready() is just like fl_wait(0.0) except no callbacks are done:
int fl_ready() {
if (XQLength(fl_display)) return 1;
# if USE_POLL
return ::poll(pollfds, 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
}
////////////////////////////////////////////////////////////////
Display *fl_display;
Window fl_message_window;
int fl_screen;
XVisualInfo *fl_visual;
Colormap fl_colormap;
static Atom WM_DELETE_WINDOW;
static Atom WM_PROTOCOLS;
static Atom fl_MOTIF_WM_HINTS;
static Atom TARGETS;
static Atom CLIPBOARD;
Atom fl_XdndAware;
Atom fl_XdndSelection;
Atom fl_XdndEnter;
Atom fl_XdndTypeList;
Atom fl_XdndPosition;
Atom fl_XdndLeave;
Atom fl_XdndDrop;
Atom fl_XdndStatus;
Atom fl_XdndActionCopy;
Atom fl_XdndFinished;
//Atom fl_XdndProxy;
static void fd_callback(int,void *) {
do_queued_events();
}
extern "C" {
static int io_error_handler(Display*) {
Fl::fatal("X I/O error");
return 0;
}
static int xerror_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;
}
}
void fl_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_open_display(d);
}
void fl_open_display(Display* d) {
fl_display = d;
WM_DELETE_WINDOW = XInternAtom(d, "WM_DELETE_WINDOW", 0);
WM_PROTOCOLS = XInternAtom(d, "WM_PROTOCOLS", 0);
fl_MOTIF_WM_HINTS = XInternAtom(d, "_MOTIF_WM_HINTS", 0);
TARGETS = XInternAtom(d, "TARGETS", 0);
CLIPBOARD = XInternAtom(d, "CLIPBOARD", 0);
fl_XdndAware = XInternAtom(d, "XdndAware", 0);
fl_XdndSelection = XInternAtom(d, "XdndSelection", 0);
fl_XdndEnter = XInternAtom(d, "XdndEnter", 0);
fl_XdndTypeList = XInternAtom(d, "XdndTypeList", 0);
fl_XdndPosition = XInternAtom(d, "XdndPosition", 0);
fl_XdndLeave = XInternAtom(d, "XdndLeave", 0);
fl_XdndDrop = XInternAtom(d, "XdndDrop", 0);
fl_XdndStatus = XInternAtom(d, "XdndStatus", 0);
fl_XdndActionCopy = XInternAtom(d, "XdndActionCopy", 0);
fl_XdndFinished = XInternAtom(d, "XdndFinished", 0);
//fl_XdndProxy = XInternAtom(d, "XdndProxy", 0);
Fl::add_fd(ConnectionNumber(d), POLLIN, fd_callback);
fl_screen = DefaultScreen(d);
fl_message_window =
XCreateSimpleWindow(d, RootWindow(d,fl_screen), 0,0,1,1,0, 0, 0);
// construct an XVisualInfo that matches the default Visual:
XVisualInfo templt; int num;
templt.visualid = XVisualIDFromVisual(DefaultVisual(d, fl_screen));
fl_visual = XGetVisualInfo(d, VisualIDMask, &templt, &num);
fl_colormap = DefaultColormap(d, fl_screen);
#if !USE_COLORMAP
Fl::visual(FL_RGB);
#endif
}
void fl_close_display() {
Fl::remove_fd(ConnectionNumber(fl_display));
XCloseDisplay(fl_display);
}
int Fl::h() {
fl_open_display();
return DisplayHeight(fl_display,fl_screen);
}
int Fl::w() {
fl_open_display();
return DisplayWidth(fl_display,fl_screen);
}
void Fl::get_mouse(int &xx, int &yy) {
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);
xx = mx;
yy = my;
}
////////////////////////////////////////////////////////////////
// Code used for paste and DnD into the program:
Fl_Widget *fl_selection_requestor;
char *fl_selection_buffer[2];
int fl_selection_length[2];
int fl_selection_buffer_length[2];
char fl_i_own_selection[2];
// Call this when a "paste" operation happens:
void Fl::paste(Fl_Widget &receiver, int clipboard) {
if (fl_i_own_selection[clipboard]) {
// We already have it, do it quickly without window server.
// Notice that the text is clobbered if set_selection is
// called in response to FL_PASTE!
Fl::e_text = fl_selection_buffer[clipboard];
Fl::e_length = fl_selection_length[clipboard];
receiver.handle(FL_PASTE);
return;
}
// otherwise get the window server to return it:
fl_selection_requestor = &receiver;
Atom property = clipboard ? CLIPBOARD : XA_PRIMARY;
XConvertSelection(fl_display, property, XA_STRING, property,
fl_xid(Fl::first_window()), fl_event_time);
}
Window fl_dnd_source_window;
Atom *fl_dnd_source_types; // null-terminated list of data types being supplied
Atom fl_dnd_type;
Atom fl_dnd_source_action;
Atom fl_dnd_action;
void fl_sendClientMessage(Window window, Atom message,
unsigned long d0,
unsigned long d1=0,
unsigned long d2=0,
unsigned long d3=0,
unsigned long d4=0)
{
XEvent e;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?