aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJan Djärv2004-02-03 16:34:57 +0000
committerJan Djärv2004-02-03 16:34:57 +0000
commit1fb3821bbd76f13b8c288122eca57f84a362d8d9 (patch)
tree5653be2dd861874f80bc0a9f65971ee21c60f0c8 /src
parente69745bba57ab29685433a0c6ea799c6494faa0f (diff)
downloademacs-1fb3821bbd76f13b8c288122eca57f84a362d8d9.tar.gz
emacs-1fb3821bbd76f13b8c288122eca57f84a362d8d9.zip
* xselect.c: Include termhooks.h and X11/Xproto.h
(x_check_property_data, x_fill_property_data) (x_property_data_to_lisp, mouse_position_for_drop) (Fx_get_atom_name, x_handle_dnd_message): New functions for DND support. (Fx_send_client_event): Moved here from xfns.c. (syms_of_xselect): Add Sx_get_atom_name and Sx_send_client_message.
Diffstat (limited to 'src')
-rw-r--r--src/xselect.c351
1 files changed, 351 insertions, 0 deletions
diff --git a/src/xselect.c b/src/xselect.c
index 8eda4b78464..e8915d0b7a9 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -30,6 +30,9 @@ Boston, MA 02111-1307, USA. */
30#include "blockinput.h" 30#include "blockinput.h"
31#include "buffer.h" 31#include "buffer.h"
32#include "process.h" 32#include "process.h"
33#include "termhooks.h"
34
35#include <X11/Xproto.h>
33 36
34struct prop_location; 37struct prop_location;
35 38
@@ -2278,6 +2281,351 @@ Positive means shift the values forward, negative means backward. */)
2278 2281
2279#endif 2282#endif
2280 2283
2284/***********************************************************************
2285 Drag and drop support
2286***********************************************************************/
2287/* Check that lisp values are of correct type for x_fill_property_data.
2288 That is, number, string or a cons with two numbers (low and high 16
2289 bit parts of a 32 bit number). */
2290
2291int
2292x_check_property_data (data)
2293 Lisp_Object data;
2294{
2295 Lisp_Object iter;
2296 int size = 0;
2297
2298 for (iter = data; CONSP (iter) && size != -1; iter = XCDR (iter), ++size)
2299 {
2300 Lisp_Object o = XCAR (iter);
2301
2302 if (! NUMBERP (o) && ! STRINGP (o) && ! CONSP (o))
2303 size = -1;
2304 else if (CONSP (o) &&
2305 (! NUMBERP (XCAR (o)) || ! NUMBERP (XCDR (o))))
2306 size = -1;
2307 }
2308
2309 return size;
2310}
2311
2312/* Convert lisp values to a C array. Values may be a number, a string
2313 which is taken as an X atom name and converted to the atom value, or
2314 a cons containing the two 16 bit parts of a 32 bit number.
2315
2316 DPY is the display use to look up X atoms.
2317 DATA is a Lisp list of values to be converted.
2318 RET is the C array that contains the converted values. It is assumed
2319 it is big enough to hol all values.
2320 FORMAT is 8, 16 or 32 and gives the size in bits for each C value to
2321 be stored in RET. */
2322
2323void
2324x_fill_property_data (dpy, data, ret, format)
2325 Display *dpy;
2326 Lisp_Object data;
2327 void *ret;
2328 int format;
2329{
2330 CARD32 val;
2331 CARD32 *d32 = (CARD32 *) ret;
2332 CARD16 *d16 = (CARD16 *) ret;
2333 CARD8 *d08 = (CARD8 *) ret;
2334 Lisp_Object iter;
2335
2336 for (iter = data; CONSP (iter); iter = XCDR (iter))
2337 {
2338 Lisp_Object o = XCAR (iter);
2339
2340 if (INTEGERP (o))
2341 val = (CARD32) XFASTINT (o);
2342 else if (FLOATP (o))
2343 val = (CARD32) XFLOAT (o);
2344 else if (CONSP (o))
2345 val = (CARD32) cons_to_long (o);
2346 else if (STRINGP (o))
2347 {
2348 BLOCK_INPUT;
2349 val = XInternAtom (dpy, (char *) SDATA (o), False);
2350 UNBLOCK_INPUT;
2351 }
2352 else
2353 error ("Wrong type, must be string, number or cons");
2354
2355 if (format == 8)
2356 *d08++ = (CARD8) val;
2357 else if (format == 16)
2358 *d16++ = (CARD16) val;
2359 else
2360 *d32++ = val;
2361 }
2362}
2363
2364/* Convert an array of C values to a Lisp list.
2365 F is the frame to be used to look up X atoms if the TYPE is XA_ATOM.
2366 DATA is a C array of values to be converted.
2367 TYPE is the type of the data. Only XA_ATOM is special, it converts
2368 each number in DATA to its corresponfing X atom as a symbol.
2369 FORMAT is 8, 16 or 32 and gives the size in bits for each C value to
2370 be stored in RET.
2371 SIZE is the number of elements in DATA.
2372
2373 Also see comment for selection_data_to_lisp_data above. */
2374
2375Lisp_Object
2376x_property_data_to_lisp (f, data, type, format, size)
2377 struct frame *f;
2378 unsigned char *data;
2379 Atom type;
2380 int format;
2381 unsigned long size;
2382{
2383 return selection_data_to_lisp_data (FRAME_X_DISPLAY (f),
2384 data, size*format/8, type, format);
2385}
2386
2387/* Get the mouse position frame relative coordinates. */
2388
2389static void
2390mouse_position_for_drop (f, x, y)
2391 FRAME_PTR f;
2392 int *x;
2393 int *y;
2394{
2395 Window root, dummy_window;
2396 int dummy;
2397
2398 BLOCK_INPUT;
2399
2400 XQueryPointer (FRAME_X_DISPLAY (f),
2401 DefaultRootWindow (FRAME_X_DISPLAY (f)),
2402
2403 /* The root window which contains the pointer. */
2404 &root,
2405
2406 /* Window pointer is on, not used */
2407 &dummy_window,
2408
2409 /* The position on that root window. */
2410 x, y,
2411
2412 /* x/y in dummy_window coordinates, not used. */
2413 &dummy, &dummy,
2414
2415 /* Modifier keys and pointer buttons, about which
2416 we don't care. */
2417 (unsigned int *) &dummy);
2418
2419
2420 /* Absolute to relative. */
2421 *x -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
2422 *y -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
2423
2424 UNBLOCK_INPUT;
2425}
2426
2427DEFUN ("x-get-atom-name", Fx_get_atom_name,
2428 Sx_get_atom_name, 1, 2, 0,
2429 doc: /* Return the X atom name for VALUE as a string.
2430VALUE may be a number or a cons where the car is the upper 16 bits and
2431the cdr is the lower 16 bits of a 32 bit value.
2432Use the display for FRAME or the current frame if FRAME is not given or nil.
2433
2434If the value is 0 or the atom is not known, return the empty string. */)
2435 (value, frame)
2436 Lisp_Object value, frame;
2437{
2438 struct frame *f = check_x_frame (frame);
2439 char *name = 0;
2440 Lisp_Object ret = Qnil;
2441 int count;
2442 Display *dpy = FRAME_X_DISPLAY (f);
2443 Atom atom;
2444
2445 if (INTEGERP (value))
2446 atom = (Atom) XUINT (value);
2447 else if (FLOATP (value))
2448 atom = (Atom) XFLOAT (value);
2449 else if (CONSP (value))
2450 atom = (Atom) cons_to_long (value);
2451 else
2452 error ("Wrong type, value must be number or cons");
2453
2454 BLOCK_INPUT;
2455 count = x_catch_errors (dpy);
2456
2457 name = atom ? XGetAtomName (dpy, atom) : "";
2458
2459 if (! x_had_errors_p (dpy))
2460 ret = make_string (name, strlen (name));
2461
2462 x_uncatch_errors (dpy, count);
2463
2464 if (atom && name) XFree (name);
2465 if (NILP (ret)) ret = make_string ("", 0);
2466
2467 UNBLOCK_INPUT;
2468
2469 return ret;
2470}
2471
2472/* Convert an XClientMessageEvent to a Lisp event of type DRAG_N_DROP_EVENT.
2473 TODO: Check if this client event really is a DND event? */
2474
2475int
2476x_handle_dnd_message (f, event, dpyinfo, bufp)
2477 struct frame *f;
2478 XClientMessageEvent *event;
2479 struct x_display_info *dpyinfo;
2480 struct input_event *bufp;
2481{
2482 Lisp_Object vec;
2483 Lisp_Object frame;
2484 unsigned long size = (8*sizeof (event->data))/event->format;
2485 int x, y;
2486
2487 XSETFRAME (frame, f);
2488
2489 vec = Fmake_vector (4, Qnil);
2490 AREF (vec, 0) = SYMBOL_NAME (x_atom_to_symbol (FRAME_X_DISPLAY (f),
2491 event->message_type));
2492 AREF (vec, 1) = frame;
2493 AREF (vec, 2) = XFASTINT (event->format);
2494 AREF (vec, 3) = x_property_data_to_lisp (f,
2495 event->data.b,
2496 event->message_type,
2497 event->format,
2498 size);
2499
2500 mouse_position_for_drop (f, &x, &y);
2501 bufp->kind = DRAG_N_DROP_EVENT;
2502 bufp->frame_or_window = Fcons (frame, vec);
2503 bufp->timestamp = CurrentTime;
2504 bufp->x = make_number (x);
2505 bufp->y = make_number (y);
2506 bufp->arg = Qnil;
2507 bufp->modifiers = 0;
2508
2509 return 1;
2510}
2511
2512DEFUN ("x-send-client-message", Fx_send_client_event,
2513 Sx_send_client_message, 6, 6, 0,
2514 doc: /* Send a client message of MESSAGE-TYPE to window DEST on DISPLAY.
2515
2516For DISPLAY, specify either a frame or a display name (a string).
2517If DISPLAY is nil, that stands for the selected frame's display.
2518DEST may be a number, in which case it is a Window id. The value 0 may
2519be used to send to the root window of the DISPLAY.
2520If DEST is a cons, it is converted to a 32 bit number
2521with the high 16 bits from the car and the lower 16 bit from the cdr. That
2522number is then used as a window id.
2523If DEST is a frame the event is sent to the outer window of that frame.
2524Nil means the currently selected frame.
2525If DEST is the string "PointerWindow" the event is sent to the window that
2526contains the pointer. If DEST is the string "InputFocus" the event is
2527sent to the window that has the input focus.
2528FROM is the frame sending the event. Use nil for currently selected frame.
2529MESSAGE-TYPE is the name of an Atom as a string.
2530FORMAT must be one of 8, 16 or 32 and determines the size of the values in
2531bits. VALUES is a list of numbers, cons and/or strings containing the values
2532to send. If a value is a string, it is converted to an Atom and the value of
2533the Atom is sent. If a value is a cons, it is converted to a 32 bit number
2534with the high 16 bits from the car and the lower 16 bit from the cdr.
2535If more values than fits into the event is given, the excessive values
2536are ignored. */)
2537 (display, dest, from, message_type, format, values)
2538 Lisp_Object display, dest, from, message_type, format, values;
2539{
2540 struct x_display_info *dpyinfo = check_x_display_info (display);
2541 Window wdest;
2542 XEvent event;
2543 Lisp_Object cons;
2544 int size;
2545 struct frame *f = check_x_frame (from);
2546 int count;
2547 int to_root;
2548
2549 CHECK_STRING (message_type);
2550 CHECK_NUMBER (format);
2551 CHECK_CONS (values);
2552
2553 if (x_check_property_data (values) == -1)
2554 error ("Bad data in VALUES, must be number, cons or string");
2555
2556 event.xclient.type = ClientMessage;
2557 event.xclient.format = XFASTINT (format);
2558
2559 if (event.xclient.format != 8 && event.xclient.format != 16
2560 && event.xclient.format != 32)
2561 error ("FORMAT must be one of 8, 16 or 32");
2562
2563 if (FRAMEP (dest) || NILP (dest))
2564 {
2565 struct frame *fdest = check_x_frame (dest);
2566 wdest = FRAME_OUTER_WINDOW (fdest);
2567 }
2568 else if (STRINGP (dest))
2569 {
2570 if (strcmp (SDATA (dest), "PointerWindow") == 0)
2571 wdest = PointerWindow;
2572 else if (strcmp (SDATA (dest), "InputFocus") == 0)
2573 wdest = InputFocus;
2574 else
2575 error ("DEST as a string must be one of PointerWindow or InputFocus");
2576 }
2577 else if (INTEGERP (dest))
2578 wdest = (Window) XFASTINT (dest);
2579 else if (FLOATP (dest))
2580 wdest = (Window) XFLOAT (dest);
2581 else if (CONSP (dest))
2582 {
2583 if (! NUMBERP (XCAR (dest)) || ! NUMBERP (XCDR (dest)))
2584 error ("Both car and cdr for DEST must be numbers");
2585 else
2586 wdest = (Window) cons_to_long (dest);
2587 }
2588 else
2589 error ("DEST must be a frame, nil, string, number or cons");
2590
2591 if (wdest == 0) wdest = dpyinfo->root_window;
2592 to_root = wdest == dpyinfo->root_window;
2593
2594 for (cons = values, size = 0; CONSP (cons); cons = XCDR (cons), ++size)
2595 ;
2596
2597 BLOCK_INPUT;
2598
2599 event.xclient.message_type
2600 = XInternAtom (dpyinfo->display, SDATA (message_type), False);
2601 event.xclient.display = dpyinfo->display;
2602
2603 /* Some clients (metacity for example) expects sending window to be here
2604 when sending to the root window. */
2605 event.xclient.window = to_root ? FRAME_OUTER_WINDOW (f) : wdest;
2606
2607 memset (event.xclient.data.b, 0, sizeof (event.xclient.data.b));
2608 x_fill_property_data (dpyinfo->display, values, event.xclient.data.b,
2609 event.xclient.format);
2610
2611 /* If event mask is 0 the event is sent to the client that created
2612 the destination window. But if we are sending to the root window,
2613 there is no such client. Then we set the event mask to 0xffff. The
2614 event then goes to clients selecting for events on the root window. */
2615 count = x_catch_errors (dpyinfo->display);
2616 {
2617 int propagate = to_root ? False : True;
2618 unsigned mask = to_root ? 0xffff : 0;
2619 XSendEvent (dpyinfo->display, wdest, propagate, mask, &event);
2620 XFlush (dpyinfo->display);
2621 }
2622 x_uncatch_errors (dpyinfo->display, count);
2623 UNBLOCK_INPUT;
2624
2625 return Qnil;
2626}
2627
2628
2281void 2629void
2282syms_of_xselect () 2630syms_of_xselect ()
2283{ 2631{
@@ -2293,6 +2641,9 @@ syms_of_xselect ()
2293 defsubr (&Sx_rotate_cut_buffers_internal); 2641 defsubr (&Sx_rotate_cut_buffers_internal);
2294#endif 2642#endif
2295 2643
2644 defsubr (&Sx_get_atom_name);
2645 defsubr (&Sx_send_client_message);
2646
2296 reading_selection_reply = Fcons (Qnil, Qnil); 2647 reading_selection_reply = Fcons (Qnil, Qnil);
2297 staticpro (&reading_selection_reply); 2648 staticpro (&reading_selection_reply);
2298 reading_selection_window = 0; 2649 reading_selection_window = 0;