📄 fl_x.cxx
字号:
break; case UnmapNotify: event = FL_HIDE; break; case Expose: Fl_X::i (window)->wait_for_expose = 0;#if 0 // try to keep windows on top even if WM_TRANSIENT_FOR does not work: // opaque move/resize window managers do not like this, so I disabled it. if (Fl::first_window ()->non_modal () && window != Fl::first_window ()) Fl::first_window ()->show ();#endif case GraphicsExpose: window->damage (FL_DAMAGE_EXPOSE, xevent.xexpose.x, xevent.xexpose.y, xevent.xexpose.width, xevent.xexpose.height); return 1; case ButtonPress: Fl::e_keysym = FL_Button + xevent.xbutton.button; set_event_xy (); checkdouble (); Fl::e_state |= (FL_BUTTON1 << (xevent.xbutton.button - 1)); event = FL_PUSH; break; case MotionNotify: set_event_xy ();#if CONSOLIDATE_MOTION send_motion = fl_xmousewin = window; return 0;#else event = FL_MOVE; break;#endif case ButtonRelease: Fl::e_keysym = FL_Button + xevent.xbutton.button; set_event_xy (); Fl::e_state &= ~(FL_BUTTON1 << (xevent.xbutton.button - 1)); event = FL_RELEASE; break; case FocusIn: event = FL_FOCUS; break; case FocusOut: event = FL_UNFOCUS; break; case KeyPress: { int keycode = xevent.xkey.keycode; fl_key_vector[keycode / 8] |= (1 << (keycode % 8)); static char buffer[21]; KeySym keysym; int len = XLookupString ((XKeyEvent *) & (xevent.xkey), buffer, 20, &keysym, 0); if (keysym && keysym < 0x400) { // a character in latin-1,2,3,4 sets // force it to type a character (not sure if this ever is needed): if (!len) { buffer[0] = char (keysym); len = 1; } // ignore all effects of shift on the keysyms, which makes it a lot // easier to program shortcuts and is Windoze-compatable: keysym = XKeycodeToKeysym (fl_display, keycode, 0); }#ifdef __sgi // You can plug a microsoft keyboard into an sgi but the extra shift // keys are not translated. Make them translate like XFree86 does: if (!keysym) switch (keycode) { case 147: keysym = FL_Meta_L; break; case 148: keysym = FL_Meta_R; break; case 149: keysym = FL_Menu; break; }#endif#if BACKSPACE_HACK // Attempt to fix keyboards that send "delete" for the key in the // upper-right corner of the main keyboard. But it appears that // very few of these remain? static int got_backspace; if (!got_backspace) { if (keysym == FL_Delete) keysym = FL_BackSpace; else if (keysym == FL_BackSpace) got_backspace = 1; }#endif // We have to get rid of the XK_KP_function keys, because they are // not produced on Windoze and thus case statements tend not to check // for them. There are 15 of these in the range 0xff91 ... 0xff9f if (keysym >= 0xff91 && keysym <= 0xff9f) { // Try to make them turn into FL_KP+'c' so that NumLock is // irrelevant, by looking at the shifted code. This matches the // behavior of the translator in Fl_win32.C, and IMHO is the // user-friendly result: unsigned long keysym1 = XKeycodeToKeysym (fl_display, keycode, 1); if (keysym1 <= 0x7f || keysym1 > 0xff9f && keysym1 <= FL_KP_Last) { keysym = keysym1 | FL_KP; buffer[0] = char (keysym1) & 0x7F; len = 1; } else { // If that failed to work, just translate them to the matching // normal function keys: static const unsigned short table[15] = { FL_F + 1, FL_F + 2, FL_F + 3, FL_F + 4, FL_Home, FL_Left, FL_Up, FL_Right, FL_Down, FL_Page_Up, FL_Page_Down, FL_End, 0xff0b /*XK_Clear */ , FL_Insert, FL_Delete }; keysym = table[keysym - 0xff91]; } } buffer[len] = 0; Fl::e_keysym = int (keysym); Fl::e_text = buffer; Fl::e_length = len; set_event_xy (); Fl::e_is_click = 0; if (Fl::event_state (FL_CTRL) && keysym == '-') buffer[0] = 0x1f; // ^_ event = FL_KEYBOARD; break; } case KeyRelease: { int keycode = xevent.xkey.keycode; fl_key_vector[keycode / 8] &= ~(1 << (keycode % 8)); set_event_xy (); } 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; break; case LeaveNotify: if (xevent.xcrossing.detail == NotifyInferior) break; set_event_xy (); Fl::e_state = xevent.xcrossing.state << 16; event = FL_LEAVE; break; case ConfigureNotify: { // 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: Window r, c; int X, Y, wX, wY; unsigned int m; XQueryPointer (fl_display, fl_xid (window), &r, &c, &X, &Y, &wX, &wY, &m); resize_bug_fix = window; window->resize (X - wX, Y - wY, xevent.xconfigure.width, xevent.xconfigure.height); return 1; } } return Fl::handle (event, window);}////////////////////////////////////////////////////////////////voidFl_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) 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.cxxFl_X *Fl_X::set_xid (Fl_Window * w, Window xid){ Fl_X *x = new Fl_X; x->xid = xid; x->other_xid = 0; x->setwindow (w); x->next = Fl_X::first; x->region = 0; x->wait_for_expose = 1; Fl_X::first = x; if (w->modal ()) { Fl::modal_ = w; fl_fix_focus (); } return x;}// 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 drawingint fl_disable_transient_for; // secret method of removing TRANSIENT_FORstatic const int childEventMask = ExposureMask;static const int XEventMask = ExposureMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask | KeymapStateMask | FocusChangeMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask;voidFl_X::make_xid (Fl_Window * w, XVisualInfo * visual, Colormap colormap){ Fl_Group::current (0); // get rid of very common user bug: forgot end() int X = w->x (); int Y = w->y (); int W = w->w (); if (W <= 0) W = 1; // X don't like zero... int H = w->h (); if (H <= 0) H = 1; // X don't like zero... if (!w->parent () && !Fl::grab ()) { // center windows in case window manager does not do anything: if (!(w->flags () & Fl_Window::FL_FORCE_POSITION)) { w->x (X = (Fl::w () - W) / 2); w->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 (w->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 = w->parent ()? fl_xid (w->window ()) : RootWindow (fl_display, fl_screen); XSetWindowAttributes attr; int mask = CWBorderPixel | CWColormap | CWEventMask | CWBitGravity; attr.event_mask = w->parent ()? childEventMask : XEventMask; attr.colormap = colormap; attr.border_pixel = 0; attr.bit_gravity = 0; // StaticGravity; attr.override_redirect = 0; if (Fl::grab ()) { attr.save_under = 1; mask |= CWSaveUnder; if (!w->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 *x = set_xid (w, XCreateWindow (fl_display, root, X, Y, W, H, 0, // borderwidth visual->depth, InputOutput, visual->visual, mask, &attr)); w->set_visible (); w->handle (FL_SHOW); // get child windows to appear w->redraw (); if (!w->parent () && !attr.override_redirect) { // Communicate all kinds 'o junk to the X Window Manager: w->label (w->label (), w->iconlabel ()); XChangeProperty (fl_display, x->xid, wm_protocols, XA_ATOM, 32, 0, (uchar *) & wm_delete_window, 1); // send size limits and border: x->sendxjunk (); // set the class property, which controls the icon used: if (w->xclass ()) { char buffer[1024]; char *p; const char *q; // truncate on any punctuation, because they break XResource lookup: for (p = buffer, q = w->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, x->xid, XA_WM_CLASS, XA_STRING, 8, 0, (unsigned char *) buffer, p - buffer - 1); } if (w->non_modal () && x->next && !fl_disable_transient_for) { // find some other window to be "transient for": Fl_Window *w = x->next->w; while (w->parent ()) w = w->window (); XSetTransientForHint (fl_display, x->xid, fl_xid (w)); } XWMHints hints; hints.flags = 0; if (fl_show_iconic) { hints.flags = StateHint; hints.initial_state = IconicState; fl_show_iconic = 0; } if (w->icon ()) { hints.icon_pixmap = (Pixmap) w->icon (); hints.flags |= IconPixmapHint; } if (hints.flags) XSetWMHints (fl_display, x->xid, &hints); } XMapWindow (fl_display, x->xid);}////////////////////////////////////////////////////////////////// Send X window stuff that can be changed over time:voidFl_X::sendxjunk (){ if (w->parent ()) 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, _motif_wm_hints, _motif_wm_hints, 32, 0, (unsigned char *) prop, 5);}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 = ""; XChangeProperty (fl_display, i->xid, XA_WM_NAME, XA_STRING, 8, 0, (uchar *) name, strlen (name)); if (!iname) iname = 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.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 { 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.)voidFl_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);}//NANOX#endif//WIN32#endif//// End of "$Id: Fl_x.cxx,v 1.1.1.1 2003/08/07 21:18:40 jasonk Exp $".
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -