String GetProperty(Window w, Atom property, Atom rtype) { GuiLock __; LLOG("GetProperty"); String result; int format; unsigned long nitems, after = 1; long offset = 0; Atom type = None; unsigned char *data; long rsize = minmax((long)(XMaxRequestSize(Xdisplay) - 100), (long)256, (long)65536); while(after > 0) { if(XGetWindowProperty(Xdisplay, w, property, offset, rsize, XFalse, rtype, &type, &format, &nitems, &after, &data) != Success) break; if(type == None) break; if(data) { int len = format == 32 ? sizeof(unsigned long) * nitems : nitems * (format >> 3); result.Cat(data, len); XFree((char *)data); offset += nitems / (32 / format); } else break; }
int x11_init(GraceApp *gapp) { X11Stuff *xstuff = gapp->gui->xstuff; XGCValues gc_val; long mrsize; int max_path_limit; xstuff->screennumber = DefaultScreen(xstuff->disp); xstuff->root = RootWindow(xstuff->disp, xstuff->screennumber); xstuff->gc = DefaultGC(xstuff->disp, xstuff->screennumber); xstuff->depth = DisplayPlanes(xstuff->disp, xstuff->screennumber); /* init colormap */ xstuff->cmap = DefaultColormap(xstuff->disp, xstuff->screennumber); /* redefine colormap, if needed */ if (gapp->gui->install_cmap == CMAP_INSTALL_ALWAYS) { xstuff->cmap = XCopyColormapAndFree(xstuff->disp, xstuff->cmap); gapp->gui->private_cmap = TRUE; } /* set GCs */ if (gapp->gui->invert) { gc_val.function = GXinvert; } else { gc_val.function = GXxor; } gcxor = XCreateGC(xstuff->disp, xstuff->root, GCFunction, &gc_val); /* XExtendedMaxRequestSize() appeared in X11R6 */ #if XlibSpecificationRelease > 5 mrsize = XExtendedMaxRequestSize(xstuff->disp); #else mrsize = 0; #endif if (mrsize <= 0) { mrsize = XMaxRequestSize(xstuff->disp); } max_path_limit = (mrsize - 3)/2; if (max_path_limit < get_max_path_limit(grace_get_canvas(gapp->grace))) { char buf[128]; sprintf(buf, "Setting max drawing path length to %d (limited by the X server)", max_path_limit); errmsg(buf); set_max_path_limit(grace_get_canvas(gapp->grace), max_path_limit); } xstuff->dpi = rint(MM_PER_INCH*DisplayWidth(xstuff->disp, xstuff->screennumber)/ DisplayWidthMM(xstuff->disp, xstuff->screennumber)); return RETURN_SUCCESS; }
static Atom send_selection(QClipboardData *d, Atom target, Window window, Atom property) { Atom atomFormat = target; int dataFormat = 0; QByteArray data; QByteArray fmt = X11->xdndAtomToString(target); if (fmt.isEmpty()) { // Not a MIME type we have DEBUG("QClipboard: send_selection(): converting to type '%s' is not supported", fmt.data()); return XNone; } DEBUG("QClipboard: send_selection(): converting to type '%s'", fmt.data()); if (X11->xdndMimeDataForAtom(target, d->source(), &data, &atomFormat, &dataFormat)) { VDEBUG("QClipboard: send_selection():\n" " property type %lx\n" " property name '%s'\n" " format %d\n" " %d bytes\n", target, X11->xdndMimeAtomToString(atomFormat).toLatin1().data(), dataFormat, data.size()); // don't allow INCR transfers when using MULTIPLE or to // Motif clients (since Motif doesn't support INCR) static Atom motif_clip_temporary = ATOM(CLIP_TEMPORARY); bool allow_incr = property != motif_clip_temporary; // X_ChangeProperty protocol request is 24 bytes const int increment = (XMaxRequestSize(X11->display) * 4) - 24; if (data.size() > increment && allow_incr) { long bytes = data.size(); XChangeProperty(X11->display, window, property, ATOM(INCR), 32, PropModeReplace, (uchar *) &bytes, 1); (void)new QClipboardINCRTransaction(window, property, atomFormat, dataFormat, data, increment); return property; } // make sure we can perform the XChangeProperty in a single request if (data.size() > increment) return XNone; // ### perhaps use several XChangeProperty calls w/ PropModeAppend? int dataSize = data.size() / (dataFormat / 8); // use a single request to transfer data XChangeProperty(X11->display, window, property, atomFormat, dataFormat, PropModeReplace, (uchar *) data.data(), dataSize); } return property; }
void p_lines(p_win *w) { p_scr *s = w->s; Display *dpy = s->xdpy->dpy; GC gc = x_getgc(s, w, FillSolid); int nmx = XMaxRequestSize(dpy)-3; int n = x_pt_count; x_pt_count = 0; while (n>1) { if (n<nmx) nmx = n; XDrawLines(dpy, w->d, gc, x_pt_list, nmx, CoordModeOrigin); n -= nmx; } if (p_signalling) p_abort(); }
void p_segments(p_win *w) { p_scr *s = w->s; Display *dpy = s->xdpy->dpy; GC gc = x_getgc(s, w, FillSolid); int nmx = (XMaxRequestSize(dpy)-3)/2; int n = x_pt_count / 2; x_pt_count = 0; while (n>0) { if (n<nmx) nmx = n; /* note: assume here that XPoint[2] identical to XSegment */ XDrawSegments(dpy, w->d, gc, (XSegment *)x_pt_list, nmx); n -= nmx; } if (p_signalling) p_abort(); }
static void handleSelectionRequest(XSelectionRequestEvent ev) { static long chunk_size; static Atom targets; int sel_len = 0; int x, y; unsigned char *dst = cutBuffer; XEvent res; sortSelectionCorners(); //printf("cx1=%d\n", cx1); for (y = cy1; y <= cy2; y++) { for (x = cx1; x <= cx2; x++) { *dst++ = bws[y * selected_model->text_width + x]; sel_len++; } *dst++ = 0x0a; sel_len++; } if (!targets) { targets = XInternAtom(display, "TARGETS", False); } if (!chunk_size) { chunk_size = XExtendedMaxRequestSize(display) / 4; if (!chunk_size) { chunk_size = XMaxRequestSize(display) / 4; } } sel_len = sel_len > chunk_size ? chunk_size : sel_len; XChangeProperty(display, ev.requestor, ev.property, XA_STRING, 8, PropModeReplace, cutBuffer, sel_len); res.xselection.property = ev.property; res.xselection.type = SelectionNotify; res.xselection.display = ev.display; res.xselection.requestor = ev.requestor; res.xselection.selection = ev.selection; res.xselection.target = ev.target; res.xselection.time = ev.time; XSendEvent(display, ev.requestor, 0, 0, &res); XFlush(display); }
void JXGC::DrawLines ( const Drawable drawable, const JSize ptCount, XPoint xpt[] ) const { const JSize kMaxPointCount = 1 + (XMaxRequestSize(*itsDisplay) - 3) / 2; JSize offset = 0; while (offset < ptCount-1) { const JSize count = JMin(ptCount - offset, kMaxPointCount); XDrawLines(*itsDisplay, drawable, itsXGC, &(xpt[offset]), count, CoordModeOrigin); offset += count - 1; } }
// Create display, and other initialization bool wxApp::OnInitGui() { #if wxUSE_LOG // Eventually this line will be removed, but for // now we don't want to try popping up a dialog // for error messages. delete wxLog::SetActiveTarget(new wxLogStderr); #endif if (!wxAppBase::OnInitGui()) return false; Display *dpy = wxGlobalDisplay(); GetMainColormap(dpy); m_maxRequestSize = XMaxRequestSize(dpy); #if !wxUSE_NANOX m_visualInfo = new wxXVisualInfo; wxFillXVisualInfo(m_visualInfo, dpy); #endif return true; }
/* put data into a selection, in response to a SelecionRequest event from * another window (and any subsequent events relating to an INCR transfer). * * Arguments are: * * A display * * A window * * The event to respond to * * A pointer to an Atom. This gets set to the property nominated by the other * app in it's SelectionRequest. Things are likely to break if you change the * value of this yourself. * * The target(UTF8_STRING or XA_STRING) to respond to * * A pointer to an array of chars to read selection data from. * * The length of the array of chars. * * In the case of an INCR transfer, the position within the array of chars * that is being processed. * * The context that event is the be processed within. */ int xcin(Display * dpy, Window * win, XEvent evt, Atom * pty, Atom target, unsigned char *txt, unsigned long len, unsigned long *pos, unsigned int *context) { unsigned long chunk_len; /* length of current chunk (for incr * transfers only) */ XEvent res; /* response to event */ static Atom inc; static Atom targets; static long chunk_size; if (!targets) { targets = XInternAtom(dpy, "TARGETS", False); } if (!inc) { inc = XInternAtom(dpy, "INCR", False); } /* We consider selections larger than a quarter of the maximum request size to be "large". See ICCCM section 2.5 */ if (!chunk_size) { chunk_size = XExtendedMaxRequestSize(dpy) / 4; if (!chunk_size) { chunk_size = XMaxRequestSize(dpy) / 4; } } switch (*context) { case XCLIB_XCIN_NONE: if (evt.type != SelectionRequest) return (0); /* set the window and property that is being used */ *win = evt.xselectionrequest.requestor; *pty = evt.xselectionrequest.property; /* reset position to 0 */ *pos = 0; /* put the data into an property */ if (evt.xselectionrequest.target == targets) { Atom types[2] = { targets, target }; /* send data all at once (not using INCR) */ XChangeProperty(dpy, *win, *pty, XA_ATOM, 32, PropModeReplace, (unsigned char *) types, (int) (sizeof(types) / sizeof(Atom)) ); } else if (len > chunk_size) { /* send INCR response */ XChangeProperty(dpy, *win, *pty, inc, 32, PropModeReplace, 0, 0); /* With the INCR mechanism, we need to know * when the requestor window changes (deletes) * its properties */ XSelectInput(dpy, *win, PropertyChangeMask); *context = XCLIB_XCIN_INCR; } else { /* send data all at once (not using INCR) */ XChangeProperty(dpy, *win, *pty, target, 8, PropModeReplace, (unsigned char *) txt, (int) len); } /* Perhaps FIXME: According to ICCCM section 2.5, we should confirm that XChangeProperty succeeded without any Alloc errors before replying with SelectionNotify. However, doing so would require an error handler which modifies a global variable, plus doing XSync after each XChangeProperty. */ /* set values for the response event */ res.xselection.property = *pty; res.xselection.type = SelectionNotify; res.xselection.display = evt.xselectionrequest.display; res.xselection.requestor = *win; res.xselection.selection = evt.xselectionrequest.selection; res.xselection.target = evt.xselectionrequest.target; res.xselection.time = evt.xselectionrequest.time; /* send the response event */ XSendEvent(dpy, evt.xselectionrequest.requestor, 0, 0, &res); XFlush(dpy); /* if len < chunk_size, then the data was sent all at * once and the transfer is now complete, return 1 */ if (len > chunk_size) return (0); else return (1); break; case XCLIB_XCIN_INCR: /* length of current chunk */ /* ignore non-property events */ if (evt.type != PropertyNotify) return (0); /* ignore the event unless it's to report that the * property has been deleted */ if (evt.xproperty.state != PropertyDelete) return (0); /* set the chunk length to the maximum size */ chunk_len = chunk_size; /* if a chunk length of maximum size would extend * beyond the end ot txt, set the length to be the * remaining length of txt */ if ((*pos + chunk_len) > len) chunk_len = len - *pos; /* if the start of the chunk is beyond the end of txt, * then we've already sent all the data, so set the * length to be zero */ if (*pos > len) chunk_len = 0; if (chunk_len) { /* put the chunk into the property */ XChangeProperty(dpy, *win, *pty, target, 8, PropModeReplace, &txt[*pos], (int) chunk_len); } else { /* make an empty property to show we've * finished the transfer */ XChangeProperty(dpy, *win, *pty, target, 8, PropModeReplace, 0, 0); } XFlush(dpy); /* all data has been sent, break out of the loop */ if (!chunk_len) *context = XCLIB_XCIN_NONE; *pos += chunk_size; /* if chunk_len == 0, we just finished the transfer, * return 1 */ if (chunk_len > 0) return (0); else return (1); break; } return (0); }
bool CUnixEventEmitter::processMessage (XEvent &event, CEventServer *server) { if (!server) server=&_InternalServer; XWindowAttributes xwa; XGetWindowAttributes (_dpy, _win, &xwa); switch (event.type) { case ButtonPress: { //nlinfo("%d %d %d", event.xbutton.button, event.xbutton.x, event.xbutton.y); float fX = (float) event.xbutton.x / (float) xwa.width; float fY = 1.0f - (float) event.xbutton.y / (float) xwa.height; TMouseButton button=getMouseButton(event.xbutton.state); switch(event.xbutton.button) { case Button1: server->postEvent(new CEventMouseDown(fX, fY, (TMouseButton)(leftButton|(button&~(leftButton|middleButton|rightButton))), this)); break; case Button2: server->postEvent(new CEventMouseDown(fX, fY, (TMouseButton)(middleButton|(button&~(leftButton|middleButton|rightButton))), this)); break; case Button3: server->postEvent(new CEventMouseDown(fX, fY, (TMouseButton)(rightButton|(button&~(leftButton|middleButton|rightButton))), this)); break; case Button4: server->postEvent(new CEventMouseWheel(fX, fY, button, true, this)); break; case Button5: server->postEvent(new CEventMouseWheel(fX, fY, button, false, this)); break; } break; } case ButtonRelease: { //nlinfo("%d %d %d", event.xbutton.button, event.xbutton.x, event.xbutton.y); float fX = (float) event.xbutton.x / (float) xwa.width; float fY = 1.0f - (float) event.xbutton.y / (float) xwa.height; switch(event.xbutton.button) { case Button1: server->postEvent(new CEventMouseUp(fX, fY, leftButton, this)); break; case Button2: server->postEvent(new CEventMouseUp(fX, fY, middleButton, this)); break; case Button3: server->postEvent(new CEventMouseUp(fX, fY, rightButton, this)); break; } break; } case MotionNotify: { TMouseButton button=getMouseButton (event.xbutton.state); // if raw mode should be emulated if(_emulateRawMode) { // when we just wrapped back the pointer to 0.5 / 0.5, ignore event if(event.xbutton.x == xwa.width / 2 && event.xbutton.y == xwa.height / 2) break; // post a CGDMouseMove with the movement delta to the event server server->postEvent( new CGDMouseMove(this, NULL /* no mouse device */, event.xbutton.x - (xwa.width / 2), (xwa.height / 2) - event.xbutton.y)); // move the pointer back to the center of the window XWarpPointer(_dpy, None, _win, None, None, None, None, (xwa.width / 2), (xwa.height / 2)); } // if in normal mouse mode else { // get the relative mouse position float fX = (float) event.xbutton.x / (float) xwa.width; float fY = 1.0f - (float) event.xbutton.y / (float) xwa.height; // post a normal mouse move event to the event server server->postEvent (new CEventMouseMove (fX, fY, button, this)); } break; } case KeyPress: { // save keycode because XFilterEvent could set it to 0 uint keyCode = event.xkey.keycode; KeySym k; static char Text[256]; int c = 0; // check if event is filtered bool filtered = XFilterEvent(&event, _win); // if key event is filtered, we shouldn't use XLookupString to retrieve KeySym if (!filtered) { Status status = XLookupNone; #ifdef X_HAVE_UTF8_STRING if (_ic) c = Xutf8LookupString(_ic, &event.xkey, Text, sizeof(Text), &k, &status); #endif if (status == XLookupNone) c = XLookupString(&event.xkey, Text, sizeof(Text), &k, NULL); } else { k = XKeycodeToKeysym(_dpy, keyCode, 0); } // send CEventKeyDown event only if keyCode is defined if (keyCode) { TKey key = getKeyFromKeySym(k); if(key == KeyNOKEY) key = getKeyFromKeycode(keyCode); // search for key in map std::map<TKey, bool>::const_iterator it = _PressedKeys.find(key); // if key is not found or value is false, that's the first time bool firstTime = (it == _PressedKeys.end()) || !it->second; server->postEvent (new CEventKeyDown (key, getKeyButton(event.xbutton.state), firstTime, this)); _PressedKeys[key] = true; // don't send a control character when deleting if (key == KeyDELETE) c = 0; } Text[c] = '\0'; if(c>0) { #ifdef X_HAVE_UTF8_STRING ucstring ucstr; ucstr.fromUtf8(Text); CEventChar *charEvent = new CEventChar (ucstr[0], getKeyButton(event.xbutton.state), this); // raw if not processed by IME charEvent->setRaw(keyCode != 0); server->postEvent (charEvent); #else for (int i = 0; i < c; i++) { CEventChar *charEvent = new CEventChar ((ucchar)(unsigned char)Text[i], getKeyButton(event.xbutton.state), this); // raw if not processed by IME charEvent->setRaw(keyCode != 0); server->postEvent (charEvent); } #endif } break; } case KeyRelease: { if (!keyRepeat(_dpy, &event)) { KeySym k; // only need to get correct KeySym int c = XLookupString(&event.xkey, NULL, 0, &k, NULL); TKey key = getKeyFromKeySym(k); if(key == KeyNOKEY) key = getKeyFromKeycode(event.xkey.keycode); server->postEvent (new CEventKeyUp (key, getKeyButton(event.xbutton.state), this)); _PressedKeys[key] = false; } break; } case SelectionRequest: { XEvent respond; XSelectionRequestEvent req = event.xselectionrequest; respond.xselection.type= SelectionNotify; respond.xselection.display= req.display; respond.xselection.requestor= req.requestor; respond.xselection.selection=req.selection; respond.xselection.target= req.target; respond.xselection.time = req.time; respond.xselection.property = req.property; if (req.property == None) { respond.xselection.property = req.target; } if (req.target == XA_TARGETS) { Atom targets[] = { XA_TARGETS, XA_STRING, XA_UTF8_STRING }; respond.xselection.property = req.property; XChangeProperty(req.display, req.requestor, req.property, XA_ATOM, 32, PropModeReplace, (unsigned char *)targets, 3 /* number of element */); } else if (req.target == XA_STRING) { respond.xselection.property = req.property; std::string str = _CopiedString.toString(); XChangeProperty(req.display, req.requestor, req.property, XA_STRING, 8, PropModeReplace, (const unsigned char*)str.c_str(), str.length()); } else if (req.target == XA_UTF8_STRING) { respond.xselection.property = req.property; std::string str = _CopiedString.toUtf8(); XChangeProperty(req.display, req.requestor, respond.xselection.property, XA_UTF8_STRING, 8, PropModeReplace, (const unsigned char*)str.c_str(), str.length()); } else { // Note: Calling XGetAtomName with arbitrary value crash the client, maybe req.target have been sanitized by X11 server respond.xselection.property = None; } XSendEvent (_dpy, req.requestor, 0, 0, &respond); break; } case SelectionClear: _SelectionOwned = false; _CopiedString = ""; break; case SelectionNotify: { Atom target = event.xselection.target; Atom actualType = 0; int actualFormat = 0; unsigned long nitems = 0, bytesLeft = 0; // some applications are sending ATOM and other TARGETS if (target == XA_TARGETS || target == XA_ATOM) { Atom *supportedTargets = NULL; // list NeL selection properties if (XGetWindowProperty(_dpy, _win, XA_NEL_SEL, 0, XMaxRequestSize(_dpy), False, AnyPropertyType, &actualType, &actualFormat, &nitems, &bytesLeft, (unsigned char**)&supportedTargets) != Success) return false; if (bytesLeft > 0) { nlwarning("Paste: Supported TARGETS list too long."); } Atom bestTarget = 0; sint bestTargetElect = 0; // Elect best type for (uint i=0; i < nitems; i++) { // nlwarning(" - Type=%s (%u)", XGetAtomName(_dpy, supportedTargets[i]), (uint)supportedTargets[i]); if (supportedTargets[i] == XA_UTF8_STRING ) { if (bestTargetElect < 2) { bestTarget = XA_UTF8_STRING; bestTargetElect = 2; } } else if (supportedTargets[i] == XA_STRING ) { if (bestTargetElect < 1) { bestTarget = XA_STRING; bestTargetElect = 1; } } } XFree(supportedTargets); if (!bestTargetElect) { nlwarning("Paste buffer is not a text buffer."); return false; } // request string conversion XConvertSelection(_dpy, XA_CLIPBOARD, bestTarget, XA_NEL_SEL, _win, CurrentTime); } else if (target == XA_UTF8_STRING || target == XA_STRING) { uint8 *data = NULL; // get selection if (XGetWindowProperty(_dpy, _win, XA_NEL_SEL, 0, XMaxRequestSize(_dpy), False, AnyPropertyType, &actualType, &actualFormat, &nitems, &bytesLeft, (unsigned char**)&data) != Success) return false; ucstring text; std::string tmpData = (const char*)data; XFree(data); // convert buffer to ucstring if (target == XA_UTF8_STRING) { text = ucstring::makeFromUtf8(tmpData); } else if (target == XA_STRING) { text = tmpData; } else { nlwarning("Unknow format %u", (uint)target); } // sent string event to event server server->postEvent (new CEventString (text, this)); } else { nlwarning("Unknow target %u", (uint)target); } break; } case FocusIn: // keyboard focus // server->postEvent (new CEventSetFocus (true, this)); if (_ic) XSetICFocus(_ic); break; case FocusOut: // keyboard focus // server->postEvent (new CEventSetFocus (false, this)); if (_ic) XUnsetICFocus(_ic); break; case KeymapNotify: break; case MappingNotify: // update keymap XRefreshKeyboardMapping((XMappingEvent *)&event); break; case DestroyNotify: // XIM server has crashed createIM(); break; case ClientMessage: if ((event.xclient.format == 32) && ((Atom)event.xclient.data.l[0] == XA_WM_DELETE_WINDOW)) { server->postEvent(new CEventDestroyWindow(this)); } break; default: // nlinfo("UnknownEvent"); // XtDispatchEvent(&event); return false; } return true; }
bool XWindowsClipboard::sendReply(Reply* reply) { assert(reply != NULL); // bail out immediately if reply is done if (reply->m_done) { LOG((CLOG_DEBUG1 "clipboard: finished reply to 0x%08x,%d,%d", reply->m_requestor, reply->m_target, reply->m_property)); return true; } // start in failed state if property is None bool failed = (reply->m_property == None); if (!failed) { LOG((CLOG_DEBUG1 "clipboard: setting property on 0x%08x,%d,%d", reply->m_requestor, reply->m_target, reply->m_property)); // send using INCR if already sending incrementally or if reply // is too large, otherwise just send it. const UInt32 maxRequestSize = 3 * XMaxRequestSize(m_display); const bool useINCR = (reply->m_data.size() > maxRequestSize); // send INCR reply if incremental and we haven't replied yet if (useINCR && !reply->m_replied) { UInt32 size = reply->m_data.size(); if (!XWindowsUtil::setWindowProperty(m_display, reply->m_requestor, reply->m_property, &size, 4, m_atomINCR, 32)) { failed = true; } } // send more INCR reply or entire non-incremental reply else { // how much more data should we send? UInt32 size = reply->m_data.size() - reply->m_ptr; if (size > maxRequestSize) size = maxRequestSize; // send it if (!XWindowsUtil::setWindowProperty(m_display, reply->m_requestor, reply->m_property, reply->m_data.data() + reply->m_ptr, size, reply->m_type, reply->m_format)) { failed = true; } else { reply->m_ptr += size; // we've finished the reply if we just sent the zero // size incremental chunk or if we're not incremental. reply->m_done = (size == 0 || !useINCR); } } } // if we've failed then delete the property and say we're done. // if we haven't replied yet then we can send a failure notify, // otherwise we've failed in the middle of an incremental // transfer; i don't know how to cancel that so i'll just send // the final zero-length property. // FIXME -- how do you gracefully cancel an incremental transfer? if (failed) { LOG((CLOG_DEBUG1 "clipboard: sending failure to 0x%08x,%d,%d", reply->m_requestor, reply->m_target, reply->m_property)); reply->m_done = true; if (reply->m_property != None) { XWindowsUtil::ErrorLock lock(m_display); XDeleteProperty(m_display, reply->m_requestor, reply->m_property); } if (!reply->m_replied) { sendNotify(reply->m_requestor, m_selection, reply->m_target, None, reply->m_time); // don't wait for any reply (because we're not expecting one) return true; } else { static const char dummy = 0; XWindowsUtil::setWindowProperty(m_display, reply->m_requestor, reply->m_property, &dummy, 0, reply->m_type, reply->m_format); // wait for delete notify return false; } } // send notification if we haven't yet if (!reply->m_replied) { LOG((CLOG_DEBUG1 "clipboard: sending notify to 0x%08x,%d,%d", reply->m_requestor, reply->m_target, reply->m_property)); reply->m_replied = true; // dump every property on the requestor window to the debug2 // log. we've seen what appears to be a bug in lesstif and // knowing the properties may help design a workaround, if // it becomes necessary. if (CLOG->getFilter() >= kDEBUG2) { XWindowsUtil::ErrorLock lock(m_display); int n; Atom* props = XListProperties(m_display, reply->m_requestor, &n); LOG((CLOG_DEBUG2 "properties of 0x%08x:", reply->m_requestor)); for (int i = 0; i < n; ++i) { Atom target; String data; char* name = XGetAtomName(m_display, props[i]); if (!XWindowsUtil::getWindowProperty(m_display, reply->m_requestor, props[i], &data, &target, NULL, False)) { LOG((CLOG_DEBUG2 " %s: <can't read property>", name)); } else { // if there are any non-ascii characters in string // then print the binary data. static const char* hex = "0123456789abcdef"; for (String::size_type j = 0; j < data.size(); ++j) { if (data[j] < 32 || data[j] > 126) { String tmp; tmp.reserve(data.size() * 3); for (j = 0; j < data.size(); ++j) { unsigned char v = (unsigned char)data[j]; tmp += hex[v >> 16]; tmp += hex[v & 15]; tmp += ' '; } data = tmp; break; } } char* type = XGetAtomName(m_display, target); LOG((CLOG_DEBUG2 " %s (%s): %s", name, type, data.c_str())); if (type != NULL) { XFree(type); } } if (name != NULL) { XFree(name); } }
static inline int maxSelectionIncr(Display *dpy) { return XMaxRequestSize(dpy) > 65536 ? 65536*4 : XMaxRequestSize(dpy)*4 - 100; }
static Bool init_x11( char * error_buf ) { /*XXX*/ /* Namely, support for -display host:0.0 etc. */ XrmQuark common_quarks_list[20]; /*XXX change number of elements if necessary */ XrmQuarkList ql = common_quarks_list; XGCValues gcv; char *common_quarks = "String." "Blinkinvisibletime.blinkinvisibletime." "Blinkvisibletime.blinkvisibletime." "Clicktimeframe.clicktimeframe." "Doubleclicktimeframe.doubleclicktimeframe." "Wheeldown.wheeldown." "Wheelup.wheelup." "Submenudelay.submenudelay." "Scrollfirst.scrollfirst." "Scrollnext.scrollnext"; char * atom_names[AI_count] = { "RESOLUTION_X", "RESOLUTION_Y", "PIXEL_SIZE", "SPACING", "RELATIVE_WEIGHT", "FOUNDRY", "AVERAGE_WIDTH", "CHARSET_REGISTRY", "CHARSET_ENCODING", "CREATE_EVENT", "WM_DELETE_WINDOW", "WM_PROTOCOLS", "WM_TAKE_FOCUS", "_NET_WM_STATE", "_NET_WM_STATE_SKIP_TASKBAR", "_NET_WM_STATE_MAXIMIZED_VERT", "_NET_WM_STATE_MAXIMIZED_HORZ", "_NET_WM_NAME", "_NET_WM_ICON_NAME", "UTF8_STRING", "TARGETS", "INCR", "PIXEL", "FOREGROUND", "BACKGROUND", "_MOTIF_WM_HINTS", "_NET_WM_STATE_MODAL", "_NET_SUPPORTED", "_NET_WM_STATE_MAXIMIZED_HORIZ", "text/plain;charset=UTF-8", "_NET_WM_STATE_STAYS_ON_TOP", "_NET_CURRENT_DESKTOP", "_NET_WORKAREA", "_NET_WM_STATE_ABOVE" }; char hostname_buf[256], *hostname = hostname_buf; guts. click_time_frame = 200; guts. double_click_time_frame = 200; guts. visible_timeout = 500; guts. invisible_timeout = 500; guts. insert = true; guts. last_time = CurrentTime; guts. ri_head = guts. ri_tail = 0; DISP = XOpenDisplay( do_display); if (!DISP) { char * disp = getenv("DISPLAY"); snprintf( error_buf, 256, "Error: Can't open display '%s'", do_display ? do_display : (disp ? disp : "")); free( do_display); do_display = nil; return false; } free( do_display); do_display = nil; XSetErrorHandler( x_error_handler); guts.main_error_handler = x_error_handler; (void)x_io_error_handler; XCHECKPOINT; guts.connection = ConnectionNumber( DISP); { struct sockaddr name; unsigned int l = sizeof( name); guts. local_connection = getsockname( guts.connection, &name, &l) >= 0 && l == 0; } #ifdef HAVE_X11_EXTENSIONS_SHAPE_H if ( XShapeQueryExtension( DISP, &guts.shape_event, &guts.shape_error)) { guts. shape_extension = true; } else { guts. shape_extension = false; } #else guts. shape_extension = false; #endif #ifdef USE_MITSHM if ( !do_no_shmem && XShmQueryExtension( DISP)) { guts. shared_image_extension = true; guts. shared_image_completion_event = XShmGetEventBase( DISP) + ShmCompletion; } else { guts. shared_image_extension = false; guts. shared_image_completion_event = -1; } #else guts. shared_image_extension = false; guts. shared_image_completion_event = -1; #endif guts. randr_extension = false; #ifdef HAVE_X11_EXTENSIONS_XRANDR_H { int dummy; if ( XRRQueryExtension( DISP, &dummy, &dummy)) guts. randr_extension = true; } #endif #ifdef HAVE_X11_EXTENSIONS_XRENDER_H { int dummy; if ( XRenderQueryExtension( DISP, &dummy, &dummy)) guts. render_extension = true; } #endif #ifdef HAVE_X11_EXTENSIONS_XCOMPOSITE_H { int dummy; if (XQueryExtension(DISP, COMPOSITE_NAME, &guts.composite_opcode, &dummy, &dummy)) guts. composite_extension = true; } #endif XrmInitialize(); guts.db = get_database(); XrmStringToQuarkList( common_quarks, common_quarks_list); guts.qString = *ql++; guts.qBlinkinvisibletime = *ql++; guts.qblinkinvisibletime = *ql++; guts.qBlinkvisibletime = *ql++; guts.qblinkvisibletime = *ql++; guts.qClicktimeframe = *ql++; guts.qclicktimeframe = *ql++; guts.qDoubleclicktimeframe = *ql++; guts.qdoubleclicktimeframe = *ql++; guts.qWheeldown = *ql++; guts.qwheeldown = *ql++; guts.qWheelup = *ql++; guts.qwheelup = *ql++; guts.qSubmenudelay = *ql++; guts.qsubmenudelay = *ql++; guts.qScrollfirst = *ql++; guts.qscrollfirst = *ql++; guts.qScrollnext = *ql++; guts.qscrollnext = *ql++; guts. mouse_buttons = XGetPointerMapping( DISP, guts. buttons_map, 256); XCHECKPOINT; guts. limits. request_length = XMaxRequestSize( DISP); guts. limits. XDrawLines = guts. limits. request_length - 3; guts. limits. XFillPolygon = guts. limits. request_length - 4; guts. limits. XDrawSegments = (guts. limits. request_length - 3) / 2; guts. limits. XDrawRectangles = (guts. limits. request_length - 3) / 2; guts. limits. XFillRectangles = (guts. limits. request_length - 3) / 2; guts. limits. XFillArcs = guts. limits. XDrawArcs = (guts. limits. request_length - 3) / 3; XCHECKPOINT; SCREEN = DefaultScreen( DISP); /* XXX - return code? */ guts. root = RootWindow( DISP, SCREEN); guts. displaySize. x = DisplayWidth( DISP, SCREEN); guts. displaySize. y = DisplayHeight( DISP, SCREEN); XQueryBestCursor( DISP, guts. root, guts. displaySize. x, /* :-) */ guts. displaySize. y, &guts. cursor_width, &guts. cursor_height); XCHECKPOINT; TAILQ_INIT( &guts.paintq); TAILQ_INIT( &guts.peventq); TAILQ_INIT( &guts.bitmap_gc_pool); TAILQ_INIT( &guts.screen_gc_pool); TAILQ_INIT( &guts.argb_gc_pool); guts. currentFocusTime = CurrentTime; guts. windows = hash_create(); guts. menu_windows = hash_create(); guts. ximages = hash_create(); gcv. graphics_exposures = false; guts. menugc = XCreateGC( DISP, guts. root, GCGraphicsExposures, &gcv); guts. resolution. x = 25.4 * guts. displaySize. x / DisplayWidthMM( DISP, SCREEN) + .5; guts. resolution. y = 25.4 * DisplayHeight( DISP, SCREEN) / DisplayHeightMM( DISP, SCREEN) + .5; guts. depth = DefaultDepth( DISP, SCREEN); guts. idepth = get_idepth(); if ( guts.depth == 1) guts. qdepth = 1; else if ( guts.depth <= 4) guts. qdepth = 4; else if ( guts.depth <= 8) guts. qdepth = 8; else guts. qdepth = 24; guts. byte_order = ImageByteOrder( DISP); guts. bit_order = BitmapBitOrder( DISP); if ( BYTEORDER == LSB32 || BYTEORDER == LSB64) guts. machine_byte_order = LSBFirst; else if ( BYTEORDER == MSB32 || BYTEORDER == MSB64) guts. machine_byte_order = MSBFirst; else { sprintf( error_buf, "UAA_001: weird machine byte order: %08x", BYTEORDER); return false; } XInternAtoms( DISP, atom_names, AI_count, 0, guts. atoms); guts. null_pointer = nilHandle; guts. pointer_invisible_count = 0; guts. files = plist_create( 16, 16); prima_rebuild_watchers(); guts. wm_event_timeout = 100; guts. menu_timeout = 200; guts. scroll_first = 200; guts. scroll_next = 50; apc_timer_create( CURSOR_TIMER); apc_timer_set_timeout(CURSOR_TIMER, 2); apc_timer_create( MENU_TIMER); apc_timer_set_timeout( MENU_TIMER, guts. menu_timeout); apc_timer_create( MENU_UNFOCUS_TIMER); apc_timer_set_timeout( MENU_UNFOCUS_TIMER, 50); if ( !prima_init_clipboard_subsystem( error_buf)) return false; if ( !prima_init_color_subsystem( error_buf)) return false; if ( !prima_init_font_subsystem( error_buf)) return false; #ifdef WITH_GTK2 if (!prima_gtk_init()) return false; #endif bzero( &guts. cursor_gcv, sizeof( guts. cursor_gcv)); guts. cursor_gcv. cap_style = CapButt; guts. cursor_gcv. function = GXcopy; gethostname( hostname, 256); hostname[255] = '\0'; XStringListToTextProperty((char **)&hostname, 1, &guts. hostname); guts. net_wm_maximization = prima_wm_net_state_read_maximization( guts. root, NET_SUPPORTED); if ( do_sync) XSynchronize( DISP, true); return true; }
static Bool initlisa(ModeInfo * mi, lisas * loop) { lisacons *lc = &Lisa[MI_SCREEN(mi)]; lisafuncs **lf = loop->function; XPoint *lp; int phase, pctr, fctr, xctr, yctr, extra_points; double xprod, yprod, xsum, ysum; xMaxLines = (XMaxRequestSize(MI_DISPLAY(mi))-3)/2; /* printf("Got xMaxLines = %d\n", xMaxLines); */ loop->nsteps = MI_CYCLES(mi); if (loop->nsteps == 0) loop->nsteps = 1; if (MI_NPIXELS(mi) > 2) { loop->color = STARTCOLOR; loop->cstep = (loop->nsteps > MI_NPIXELS(mi)) ? loop->nsteps / MI_NPIXELS(mi) : 1; } else { loop->color = MI_WHITE_PIXEL(mi); loop->cstep = 0; } extra_points = loop->cstep - (loop->nsteps % loop->cstep); lc->maxcycles = (MAXCYCLES * loop->nsteps) - 1; loop->cstep = ( loop->nsteps > MI_NPIXELS(mi) ) ? loop->nsteps / MI_NPIXELS(mi) : 1; /* printf("Got cstep = %d\n", loop->cstep); */ loop->melting = 0; loop->nfuncs = 1; loop->pistep = 2.0 * M_PI / (double) loop->nsteps; loop->center.x = lc->width / 2; loop->center.y = lc->height / 2; loop->radius = (int) MI_SIZE(mi); CHECK_RADIUS(loop, lc); loop->dx = NRAND(XVMAX); loop->dy = NRAND(YVMAX); loop->dx++; loop->dy++; #if defined STARTFUNC lf[0] = &Function[STARTFUNC]; #else /* STARTFUNC */ lf[0] = &Function[NRAND(NUMSTDFUNCS)]; #endif /* STARTFUNC */ if ((lp = loop->lastpoint = (XPoint *) calloc(loop->nsteps+extra_points, sizeof (XPoint))) == NULL) { free_lisa(lc); return False; } phase = lc->loopcount % loop->nsteps; #if defined DEBUG printf( "nsteps = %d\tcstep = %d\tmrs = %d\textra_points = %d\n", loop->nsteps, loop->cstep, xMaxLines, extra_points ); PRINT_FUNC(lf[0]); #endif /* DEBUG */ for (pctr = 0; pctr < loop->nsteps; pctr++) { loop->phi = (double) (pctr - phase) * loop->pistep; loop->theta = (double) (pctr + phase) * loop->pistep; fctr = loop->nfuncs; xsum = ysum = 0.0; while (fctr--) { xprod = yprod = (double) loop->radius; xctr = lf[fctr]->nx; yctr = lf[fctr]->ny; while (xctr--) xprod *= sin(lf[fctr]->xcoeff[xctr] * loop->theta); while (yctr--) yprod *= sin(lf[fctr]->ycoeff[yctr] * loop->phi); xsum += xprod; ysum += yprod; } if (loop->nfuncs > 1) { xsum /= 2.0; ysum /= 2.0; } xsum += (double) loop->center.x; ysum += (double) loop->center.y; lp[pctr].x = (int) ceil(xsum); lp[pctr].y = (int) ceil(ysum); } /* this fills in the extra points, so we can use segment-drawing calls */ for (pctr = loop->nsteps; pctr < loop->nsteps + extra_points; pctr++) { lp[pctr].x=lp[pctr - loop->nsteps].x; lp[pctr].y=lp[pctr - loop->nsteps].y; } #if defined DRAWLINES loop->linewidth = LINEWIDTH; /* #### make this a resource */ if (loop->linewidth == 0) loop->linewidth = 1; if (loop->linewidth < 0) loop->linewidth = NRAND(-loop->linewidth) + 1; XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), loop->linewidth, LINESTYLE, LINECAP, LINEJOIN); #endif /* DRAWLINES */ if ( loop->cstep < xMaxLines ) { /* we can send each color segment in a single request * because the max request length is long enough * and because we have padded out the array to have extra elements * to support calls which would otherwise fall off the end*/ for (pctr = 0; pctr < loop->nsteps; pctr+=loop->cstep) { /* Set the color */ SET_COLOR(); #if defined DRAWLINES XDrawLines(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), &lp[pctr], loop->cstep, CoordModeOrigin ); #else /* DRAWLINES */ XDrawPoints(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), &lp[pctr], loop->cstep, CoordModeOrigin ); #endif /* DRAWLINES */ } } else { /* do it one by one as before */ for (pctr = 0; pctr < loop->nsteps; pctr++ ) { SET_COLOR(); #if defined DRAWLINES XDrawLine(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), lp[pctr].x, lp[pctr].y, lp[pctr+1 % loop->nsteps].x, lp[pctr+1 % loop->nsteps].y); #else /* DRAWLINES */ XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi), lp[pctr].x, lp[pctr].y); #endif /* DRAWLINES */ } } #if defined DRAWLINES XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 1, LINESTYLE, LINECAP, LINEJOIN); #endif /* DRAWLINES */ return True; }
/* Put data into a selection, in response to a SelecionRequest event from * another window (and any subsequent events relating to an INCR transfer). * * Arguments are: * A display * A window * The event to respond to * A pointer to an Atom. This gets set to the property nominated by the other * app in it's SelectionRequest. Things are likely to break if you change the * value of this yourself. * The target (UTF8_STRING or XA_STRING) to respond to * A pointer to an array of chars to read selection data from. * The length of the array of chars. * In case of an INCR transfer, the position within the array of chars that's being processed. * The context that event is the be processed within. */ static int xcin( Display*dpy, Window*win, XEvent evt, Atom*prop, Atom trg, uchar*txt, ulong len, ulong*pos, uint *ctx ) { ulong chunk_len; /* length of current chunk (for incr transfers only) */ XEvent resp; /* response to event */ static Atom inc; static Atom targets; static long chunk_size; if (!targets) { targets = XInternAtom(dpy, "TARGETS", False); } if (!inc) { inc = XInternAtom(dpy, "INCR", False); } /* Treat selections larger than 1/4 of the max request size as "large" per ICCCM sect. 2.5 */ if (!chunk_size) { chunk_size = XExtendedMaxRequestSize(dpy) / 4; if (!chunk_size) { chunk_size = XMaxRequestSize(dpy) / 4; } } switch (*ctx) { case XCLIB_XCIN_NONE: { if (evt.type != SelectionRequest) { return (0); } *win = evt.xselectionrequest.requestor; *prop = evt.xselectionrequest.property; *pos = 0; if (evt.xselectionrequest.target == targets) { /* put the data into an property */ Atom types[2]; int size=(int)(sizeof(types)/sizeof(Atom)); types[0]=targets; types[1]=trg; /* send data all at once (not using INCR) */ XChangeProperty(dpy,*win,*prop,XA_ATOM,32,PropModeReplace,(uchar*)types,size); } else if (len > chunk_size) { XChangeProperty(dpy,*win,*prop,inc,32,PropModeReplace,0,0); /* send INCR response */ /* With INCR, we need to know when requestor window changes/deletes properties */ XSelectInput(dpy, *win, PropertyChangeMask); *ctx = XCLIB_XCIN_INCR; } else { XChangeProperty(dpy,*win,*prop,trg,8,PropModeReplace,(uchar*)txt,(int)len); /* All, not INCR */ } /* FIXME? According to ICCCM section 2.5, we should confirm that X ChangeProperty succeeded without any Alloc errors before replying with SelectionNotify. However, doing so would require an error handler which modifies a global variable, plus doing XSync after each X ChangeProperty. */ resp.xselection.property = *prop; resp.xselection.type = SelectionNotify; resp.xselection.display = evt.xselectionrequest.display; resp.xselection.requestor = *win; resp.xselection.selection = evt.xselectionrequest.selection; resp.xselection.target = evt.xselectionrequest.target; resp.xselection.time = evt.xselectionrequest.time; XSendEvent(dpy, evt.xselectionrequest.requestor, 0, 0, &resp); /* send response event */ XFlush(dpy); return (len > chunk_size) ? 0 : 1; /* if data sent all at once, transfer is complete. */ break; } case XCLIB_XCIN_INCR: { if (evt.type != PropertyNotify) { return (0); } /* ignore non-property events */ if (evt.xproperty.state != PropertyDelete) { return (0); } /* only interest in deleted props */ chunk_len = chunk_size; /* set length to max size */ /* if a max-sized chunk length would extend past end, set length to remaining txt length */ if ((*pos + chunk_len) > len) { chunk_len = len - *pos; } /* if start of chunk is beyond end of txt, then we've sent all data, so set length to zero */ if (*pos > len) { chunk_len = 0; } if (chunk_len) { /* put chunk into property */ XChangeProperty(dpy,*win,*prop,trg,8,PropModeReplace,&txt[*pos],(int)chunk_len); } else { XChangeProperty(dpy,*win,*prop,trg,8,PropModeReplace,0,0); /* empty prop shows we're done */ } XFlush(dpy); if (!chunk_len) { *ctx = XCLIB_XCIN_NONE; } /* all data is sent, break out of the loop */ *pos += chunk_size; return (chunk_len==0) ? 1 : 0; /* chunk_len == 0 means we finished the transfer. */ break; } } return (0); }