/* This does a drag. This is copied somewhat from the dnd Xt code by César Crusius so it should behave almost exactly the way his does. From is the sending window. data_type is a dnd type in coolwidget.h, data is the actual data, and length is its length. pointer state is the state of the pointer. I set the pointer state to that *during* the drag, not before. See eh_editor in editwidget.c for details. */ void CDrag (Window from, int data_type, unsigned char *data, int length, unsigned long pointer_state) { XEvent e; long x, y; Window root; Window target, dispatch; #ifdef DND_DEBUG printf ("Drag start\n"); #endif root = DefaultRootWindow (CDisplay); XChangeProperty (CDisplay, root, DndSelection, XA_STRING, 8, PropModeReplace, data, length); XGrabPointer (CDisplay, root, False, ButtonMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeSync, GrabModeAsync, root, DndCursor[data_type].CursorID, CurrentTime); do { XAllowEvents (CDisplay, SyncPointer, CurrentTime); XNextEvent (CDisplay, &e); } while (e.type != ButtonRelease); XUngrabPointer (CDisplay, CurrentTime); if (!e.xbutton.subwindow) { #ifdef DND_DEBUG printf ("Pointer on root window, Drag end\n"); #endif return; } target = my_XmuClientWindow (CDisplay, e.xbutton.subwindow); if (target == e.xbutton.subwindow) dispatch = target; else dispatch = PointerWindow; x = e.xbutton.x_root; y = e.xbutton.y_root; e.xclient.type = ClientMessage; e.xclient.display = CDisplay; e.xclient.message_type = DndProtocol; e.xclient.format = 32; e.xclient.window = target; e.xclient.data.l[0] = data_type; e.xclient.data.l[1] = pointer_state; e.xclient.data.l[2] = from; e.xclient.data.l[3] = x + y * 65536L; e.xclient.data.l[4] = 1; /* Send the drop message */ XSendEvent (CDisplay, dispatch, True, NoEventMask, &e); #ifdef DND_DEBUG printf ("Drop send to window %ld from %ld, Drag end\n", target, from); #endif }
static inline void post_mouse_button_event(uiohook_event * const event) { #ifdef USE_XTEST Window ret_root; Window ret_child; int root_x; int root_y; int win_x; int win_y; unsigned int mask; Window win_root = XDefaultRootWindow(properties_disp); Bool query_status = XQueryPointer(properties_disp, win_root, &ret_root, &ret_child, &root_x, &root_y, &win_x, &win_y, &mask); if (query_status) { if (event->data.mouse.x != root_x || event->data.mouse.y != root_y) { // Move the pointer to the specified position. XTestFakeMotionEvent(properties_disp, -1, event->data.mouse.x, event->data.mouse.y, 0); } else { query_status = False; } } if (event->type == EVENT_MOUSE_WHEEL) { // Wheel events should be the same as click events on X11. // type, amount and rotation if (event->data.wheel.rotation < 0) { XTestFakeButtonEvent(properties_disp, WheelUp, True, 0); XTestFakeButtonEvent(properties_disp, WheelUp, False, 0); } else { XTestFakeButtonEvent(properties_disp, WheelDown, True, 0); XTestFakeButtonEvent(properties_disp, WheelDown, False, 0); } } else if (event->type == EVENT_MOUSE_PRESSED) { XTestFakeButtonEvent(properties_disp, event->data.mouse.button, True, 0); } else if (event->type == EVENT_MOUSE_RELEASED) { XTestFakeButtonEvent(properties_disp, event->data.mouse.button, False, 0); } else if (event->type == EVENT_MOUSE_CLICKED) { XTestFakeButtonEvent(properties_disp, event->data.mouse.button, True, 0); XTestFakeButtonEvent(properties_disp, event->data.mouse.button, False, 0); } if (query_status) { // Move the pointer back to the original position. XTestFakeMotionEvent(properties_disp, -1, root_x, root_y, 0); } #else XButtonEvent btn_event; btn_event.serial = 0x00; btn_event.send_event = False; btn_event.display = properties_disp; btn_event.time = CurrentTime; btn_event.same_screen = True; btn_event.root = DefaultRootWindow(properties_disp); btn_event.window = btn_event.root; btn_event.subwindow = None; btn_event.type = 0x00; btn_event.state = 0x00; btn_event.x_root = 0; btn_event.y_root = 0; btn_event.x = 0; btn_event.y = 0; btn_event.button = 0x00; btn_event.state = convert_to_native_mask(event->mask); btn_event.x = event->data.mouse.x; btn_event.y = event->data.mouse.y; #if defined(USE_XINERAMA) || defined(USE_XRANDR) uint8_t screen_count; screen_data *screens = hook_create_screen_info(&screen_count); if (screen_count > 1) { btn_event.x += screens[0].x; btn_event.y += screens[0].y; } if (screens != NULL) { free(screens); } #endif // These are the same because Window == Root Window. btn_event.x_root = btn_event.x; btn_event.y_root = btn_event.y; if (event->type == EVENT_MOUSE_WHEEL) { // type, amount and rotation if (event->data.wheel.rotation < 0) { btn_event.button = WheelUp; } else { btn_event.button = WheelDown; } } if (event->type != EVENT_MOUSE_RELEASED) { // FIXME Where do we set event->button? btn_event.type = ButtonPress; XSendEvent(properties_disp, InputFocus, False, ButtonPressMask, (XEvent *) &btn_event); } if (event->type != EVENT_MOUSE_PRESSED) { btn_event.type = ButtonRelease; XSendEvent(properties_disp, InputFocus, False, ButtonReleaseMask, (XEvent *) &btn_event); } #endif }
static int initEGL(void) { NativeWindowType window = 0; printf ("GL init\n"); EGLint numConfigs; EGLint majorVersion; EGLint minorVersion; #if defined(USE_X11) enum { _NET_WM_STATE_REMOVE =0, _NET_WM_STATE_ADD = 1, _NET_WM_STATE_TOGGLE =2 }; Window sRootWindow; XSetWindowAttributes sWA; unsigned int ui32Mask; int i32Depth; #endif EGLint *attribList = NULL; if (use_fsaa) { printf( "GLES: Using Full Scene Antialiasing\n" ); attribList = attrib_list_fsaa; } else { attribList = attrib_list; } #if defined(USE_X11) // Initializes the display and screen x11Display = XOpenDisplay( ":0" ); if (!x11Display) { printf("GLES Error: Unable to open X display\n"); return -1; } x11Screen = XDefaultScreen( x11Display ); // Gets the display parameters so we can pass the same parameters to the window to be created. sRootWindow = RootWindow(x11Display, x11Screen); i32Depth = DefaultDepth(x11Display, x11Screen); px11Visual = &x11Visual; XMatchVisualInfo( x11Display, x11Screen, i32Depth, TrueColor, px11Visual); if (!px11Visual) { printf("GLES Error: Unable to acquire visual\n"); return -1; } // Colormap of the specified visual type for the display. x11Colormap = XCreateColormap( x11Display, sRootWindow, px11Visual->visual, AllocNone ); sWA.colormap = x11Colormap; // List of events to be handled by the application. Add to these for handling other events. sWA.event_mask = StructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask; // Display capabilities list. ui32Mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap; // Creates the X11 window x11Window = XCreateWindow( x11Display, RootWindow(x11Display, x11Screen), 0, 0, iResX, iResY, 0, CopyFromParent, InputOutput, CopyFromParent, ui32Mask, &sWA); // Make the window viewable and flush the output buffer. XMapWindow(x11Display, x11Window); XFlush(x11Display); // Make the window fullscreen unsigned char fullScreen = 1; Atom wmState = XInternAtom(x11Display, "_NET_WM_STATE", False); Atom wmFullScreen = XInternAtom(x11Display,"_NET_WM_STATE_FULLSCREEN", False); XEvent xev; xev.xclient.type = ClientMessage; xev.xclient.serial = 0; xev.xclient.send_event = True; xev.xclient.window = x11Window; xev.xclient.message_type = wmState; xev.xclient.format = 32; xev.xclient.data.l[0] = (fullScreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE); xev.xclient.data.l[1] = wmFullScreen; xev.xclient.data.l[2] = 0; XSendEvent(x11Display, DefaultRootWindow(x11Display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); display = eglGetDisplay( (EGLNativeDisplayType)x11Display ); window = x11Window; #else display = eglGetDisplay( (EGLNativeDisplayType)0 ); #endif if( display == EGL_NO_DISPLAY ) { printf( "GLES EGL Error: GL No Display\n" ); return -1; } if( !eglInitialize( display, &majorVersion, &minorVersion ) ) { printf( "GLES EGL Error: eglInitialize failed\n" ); return -1; } if( !eglChooseConfig( display, attribList, &config, 1, &numConfigs ) ) { printf( "GLES EGL Error: eglChooseConfig failed\n" ); return -1; } context = eglCreateContext( display, config, NULL, NULL ); if( context==0 ) { printf( "GLES EGL Error: eglCreateContext failed\n" ); return -1; } #ifdef FAKE_WINDOW // broken Caanoo libs won't accept NULL window window = (NativeWindowType)1; #endif surface = eglCreateWindowSurface( display, config, window, NULL ); if (!TestEGLError("eglCreateWindowSurface")) return -1; eglMakeCurrent( display, surface, surface, context ); if (!TestEGLError("eglMakeCurrent")) return -1; printf("GLES init ok\n"); return 0; }
// only used internally void makeNativeWindow() { #ifdef __FOR_XORG__ __x_display = XOpenDisplay(NULL); // open the standard display (the primary screen) if (__x_display == NULL) { printf("cannot connect to X server\n"); } Window root = DefaultRootWindow(__x_display); // get the root window (usually the whole screen) XSetWindowAttributes swa; swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask | KeyReleaseMask; __display_width=1024; __display_height=768; // xorg hard coded for now int s = DefaultScreen(__x_display); __win = XCreateSimpleWindow(__x_display, root, 10, 10, __display_width, __display_height, 1, BlackPixel(__x_display, s), WhitePixel(__x_display, s)); XSelectInput(__x_display, __win, ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask); XSetWindowAttributes xattr; Atom atom; int one = 1; xattr.override_redirect = False; XChangeWindowAttributes(__x_display, __win, CWOverrideRedirect, &xattr); /* atom = XInternAtom(__x_display, "_NET_WM_STATE_FULLSCREEN", True); XChangeProperty(__x_display, win, XInternAtom(__x_display, "_NET_WM_STATE", True), XA_ATOM, 32, PropModeReplace, (unsigned char *)&atom, 1); */ XWMHints hints; hints.input = True; hints.flags = InputHint; XSetWMHints(__x_display, __win, &hints); XMapWindow(__x_display, __win); // make the window visible on the screen XStoreName(__x_display, __win, "GLES2.0 framework"); // give the window a name // NB - RPi needs to use EGL_DEFAULT_DISPLAY that some X configs dont seem to like __egl_display = eglGetDisplay((EGLNativeDisplayType) __x_display); if (__egl_display == EGL_NO_DISPLAY) { printf("Got no EGL display.\n"); } __eventWin = __win; Cursor invisibleCursor; Pixmap bitmapNoData; XColor black; static char noData[] = { 0,0,0,0,0,0,0,0 }; black.red = black.green = black.blue = 0; bitmapNoData = XCreateBitmapFromData(__x_display, __win, noData, 8, 8); invisibleCursor = XCreatePixmapCursor(__x_display, bitmapNoData, bitmapNoData, &black, &black, 0, 0); XDefineCursor(__x_display,__win, invisibleCursor); XFreeCursor(__x_display, invisibleCursor); #endif //__FOR_XORG__ #ifdef __FOR_RPi__ bcm_host_init(); int32_t success = 0; // create an EGL window surface, passing context width/height success = graphics_get_display_size(0 /* LCD */ , &__display_width, &__display_height); if (success < 0) { printf("unable to get display size\n"); //return EGL_FALSE; } __x_display = XOpenDisplay(NULL); // open the standard display (the primary screen) if (__x_display == NULL) { printf("cannot connect to X server\n"); } Window root = DefaultRootWindow(__x_display); // get the root window (usually the whole screen) XSetWindowAttributes swa; swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask | KeyReleaseMask; int s = DefaultScreen(__x_display); __eventWin = XCreateSimpleWindow(__x_display, root, 0, 0, __display_width, __display_height, 1, BlackPixel(__x_display, s), WhitePixel(__x_display, s)); XSelectInput(__x_display, __eventWin, ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask); XSetWindowAttributes xattr; Atom atom; int one = 1; xattr.override_redirect = False; XChangeWindowAttributes(__x_display, __eventWin, CWOverrideRedirect, &xattr); XWMHints hints; hints.input = True; hints.flags = InputHint; XSetWMHints(__x_display, __eventWin, &hints); XMapWindow(__x_display, __eventWin); // make the window visible on the screen XStoreName(__x_display, __eventWin, "Event trap"); // give the window a name // we have to be full screen to capture all mouse events // TODO consider using warp mouse to report relative motions // instead of absolute... XFlush(__x_display); // you have to flush or bcm seems to prevent window coming up? Atom wmState = XInternAtom(__x_display, "_NET_WM_STATE", False); Atom fullScreen = XInternAtom(__x_display, "_NET_WM_STATE_FULLSCREEN", False); XEvent xev; xev.xclient.type = ClientMessage; xev.xclient.serial = 0; xev.xclient.send_event = True; xev.xclient.window = __eventWin; xev.xclient.message_type = wmState; xev.xclient.format = 32; xev.xclient.data.l[0] = 1; //_NET_WM_STATE_ADD xev.xclient.data.l[1] = fullScreen; xev.xclient.data.l[2] = 0; XSendEvent(__x_display, root, False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); XFlush(__x_display); // you have to flush or bcm seems to prevent window coming up? static EGL_DISPMANX_WINDOW_T nativewindow; DISPMANX_ELEMENT_HANDLE_T dispman_element; DISPMANX_DISPLAY_HANDLE_T dispman_display; DISPMANX_UPDATE_HANDLE_T dispman_update; VC_RECT_T dst_rect; VC_RECT_T src_rect; // printf("display size %i,%i\n",__display_width,__display_height); dst_rect.x = 0; dst_rect.y = 0; dst_rect.width = __display_width; dst_rect.height = __display_height; src_rect.x = 0; src_rect.y = 0; src_rect.width = __display_width << 16; src_rect.height = __display_height << 16; dispman_display = vc_dispmanx_display_open(0 /* LCD */ ); dispman_update = vc_dispmanx_update_start(0); //VC_DISPMANX_ALPHA_T alpha = { DISPMANX_FLAGS_ALPHA_FROM_SOURCE | DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS,255,0 }; VC_DISPMANX_ALPHA_T alpha = { DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS,255,0 }; dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display, 0 /*layer */ , &dst_rect, 0 /*src */ , &src_rect, DISPMANX_PROTECTION_NONE, &alpha /*alpha */ , 0 /*clamp */ , 0 /*transform */ ); nativewindow.element = dispman_element; nativewindow.width = __display_width; nativewindow.height = __display_height; vc_dispmanx_update_submit_sync(dispman_update); __win = &nativewindow; __egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); #endif //__FOR_RPi__ #ifdef __FOR_RPi_noX__ bcm_host_init(); int32_t success = 0; success = graphics_get_display_size(0 /* LCD */ , &__display_width, &__display_height); if (success < 0) { printf("unable to get display size\n"); //return EGL_FALSE; } static EGL_DISPMANX_WINDOW_T nativewindow; DISPMANX_ELEMENT_HANDLE_T dispman_element; DISPMANX_DISPLAY_HANDLE_T dispman_display; DISPMANX_UPDATE_HANDLE_T dispman_update; VC_RECT_T dst_rect; VC_RECT_T src_rect; dst_rect.x = 0; dst_rect.y = 0; dst_rect.width = __display_width; dst_rect.height = __display_height; src_rect.x = 0; src_rect.y = 0; src_rect.width = __display_width << 16; src_rect.height = __display_height << 16; dispman_display = vc_dispmanx_display_open(0 /* LCD */ ); dispman_update = vc_dispmanx_update_start(0); VC_DISPMANX_ALPHA_T alpha = { DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS,255,0 }; dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display, 0 /*layer */ , &dst_rect, 0 /*src */ , &src_rect, DISPMANX_PROTECTION_NONE, &alpha /*alpha */ , 0 /*clamp */ , 0 /*transform */ ); nativewindow.element = dispman_element; nativewindow.width = __display_width; nativewindow.height = __display_height; vc_dispmanx_update_submit_sync(dispman_update); __win = &nativewindow; __egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (__egl_display == EGL_NO_DISPLAY) { printf("Got no EGL display.\n"); } #endif //__FOR_RPi_noX__ }
void CL_Clipboard_X11::event_selection_request(XSelectionRequestEvent &xselectionrequest) { XSelectionRequestEvent *rptr = &xselectionrequest; if (rptr->requestor == window) return; // Ignore request if from self XEvent new_event; new_event.xselection.type = SelectionNotify; new_event.xselection.display = rptr->display; new_event.xselection.requestor = rptr->requestor; new_event.xselection.selection = rptr->selection; new_event.xselection.target = rptr->target; new_event.xselection.property = None; new_event.xselection.time = rptr->time; Atom xa_targets = XInternAtom(disp, "TARGETS", False); Atom xa_multiple = XInternAtom(disp, "MULTIPLE", False); struct AtomPair { Atom target; Atom property; } *multi_ptr = NULL; unsigned char *data_ptr = NULL; int num_multi = 0; int index_multi = -1; if (rptr->target == xa_multiple) { unsigned long number_items; int actual_format; Atom actual_type; data_ptr = x11_window->get_property( rptr->requestor, rptr->property, &number_items, &actual_format, &actual_type ); if ( data_ptr ) { num_multi = number_items / 2; multi_ptr = (struct AtomPair *) data_ptr; } index_multi = 0; } while( index_multi < num_multi) { Window xtarget; Atom xproperty; new_event.xselection.property = None; if (multi_ptr) { xtarget = multi_ptr[index_multi].target; xproperty = multi_ptr[index_multi].property; index_multi++; }else { xtarget = rptr->target; xproperty = rptr->property; } if (xtarget == xa_targets) { long new_targets[1]; new_targets[0] = XA_STRING; XChangeProperty( disp, rptr->requestor, xproperty, xa_targets, 32, PropModeReplace, (unsigned char *) new_targets, 1); new_event.xselection.property = xproperty; }else { if (xtarget == XA_STRING) { XChangeProperty(disp, rptr->requestor, xproperty, xtarget, 8, PropModeReplace, (const unsigned char*) clipboard_current.c_str(), clipboard_current.size()); new_event.xselection.property = xproperty; } } XSendEvent( disp, rptr->requestor, False, 0, &new_event ); if (!num_multi) break; } if (data_ptr) { XFree(data_ptr); } }
void X11Window::create(XVisualInfo *visual, DisplayWindowSite *new_site, const DisplayWindowDescription &desc) { site = new_site; // Reset all variables close_window(); handle.screen = visual->screen; atoms = X11Atoms(handle.display); int disp_width_px = XDisplayWidth(handle.display, handle.screen); int disp_height_px = XDisplayHeight(handle.display, handle.screen); int disp_width_mm = XDisplayWidthMM(handle.display, handle.screen); // Get DPI of screen or use 96.0f if Xlib doesn't have a value. ppi = (disp_width_mm < 24) ? 96.0f : (25.4f * static_cast<float>(disp_width_px) / static_cast<float>(disp_width_mm)); // Update pixel ratio. set_pixel_ratio(pixel_ratio); // Get X11 root window. auto _root_window = RootWindow(handle.display, handle.screen); // Get and validate initial window position and size. int win_x = desc.get_position().left * pixel_ratio; int win_y = desc.get_position().top * pixel_ratio; int win_width = desc.get_size().width * pixel_ratio; int win_height = desc.get_size().height * pixel_ratio; if (win_width <= 0) throw Exception("Invalid window width."); if (win_height <= 0) throw Exception("Invalid window height."); // Set values if fullscreen requested. if (desc.is_fullscreen()) { win_x = 0; win_y = 0; win_width = disp_width_px; win_height = disp_height_px; } // Center window if position supplied is (-1, -1) if (win_x == -1 && win_y == -1) { win_x = (disp_width_px - win_width)/2 - 1; win_y = (disp_height_px - win_height)/2 - 1; } // Set minimum and maximum size this->resize_allowed = desc.get_allow_resize() || desc.is_fullscreen(); // Fullscreen mode needs a resizable window. if (resize_allowed) { minimum_size = Size(_ResizeMinimumSize_, _ResizeMinimumSize_); maximum_size = Size(0, 0); // No maximum size by default. } else { minimum_size = Size(win_width, win_height); maximum_size = Size(win_width, win_height); } // Setup X11 size hints. this->size_hints = XAllocSizeHints(); if (size_hints == NULL) throw Exception("Failed to allocate X11 XSizeHints structure."); size_hints->flags = PMinSize | (resize_allowed ? 0 : PMaxSize); size_hints->flags |= PResizeInc | PBaseSize | PWinGravity; // x, y, width, height are obsolete. size_hints->flags |= USSize | USPosition; // See http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#idm140200472522864 size_hints->min_width = minimum_size.width; size_hints->min_height = minimum_size.height; size_hints->max_width = maximum_size.width; size_hints->max_height = maximum_size.height; size_hints->width_inc = 1; size_hints->height_inc = 1; size_hints->base_width = win_width; size_hints->base_height = win_height; size_hints->win_gravity = NorthWestGravity; // Setup X11 colormap. // // The X.Org XServer implementation used on most systems requires that // a color-map be set for the window. Additionally, windows with a // different color-depth than its parent must have the border-pixel flag // set when creating them. Failure to do either will cause XCreateWindow() // to result in a BadMatch error. // // Source: stackoverflow.com/questions/3645632 color_map = XCreateColormap(handle.display, _root_window, visual->visual, AllocNone); // Static popups are unresizable captionless popup windows. // These windows should not be decorated. bool is_static_popup = desc.is_popup() && !desc.has_caption() && !desc.get_allow_resize(); // Tell X11 to perserve graphical content under small popup windows to avoid redraws. bool save_under = desc.is_popup() && ( (win_width * win_height) < (256 * 256 * pixel_ratio * pixel_ratio) ); // Setup window attributes. XSetWindowAttributes attr = XSetWindowAttributes { .background_pixmap = None, /* default */ .background_pixel = 0ul, /* default: undefined */ .border_pixmap = CopyFromParent, /* default */ .border_pixel = 0ul, /* see color_map details above */ .bit_gravity = ForgetGravity, /* default */ .win_gravity = NorthWestGravity, /* default */ .backing_store = NotUseful, /* default */ .backing_planes = -1ul, /* default */ .backing_pixel = 0ul, /* default */ .save_under = save_under ? True : False, .event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | KeymapStateMask | ExposureMask // | VisibilityChangeMask | StructureNotifyMask | FocusChangeMask | PropertyChangeMask , .do_not_propagate_mask = NoEventMask, /* default */ .override_redirect = is_static_popup ? True : False, .colormap = color_map, /* see color_map details above */ .cursor = None /* default; Let X11 handle the cursor for now. */ }; this->system_cursor = XCreateFontCursor(handle.display, XC_left_ptr); // This is allowed to fail log_event("debug", "clan::X11Window::create(): Creating window..."); log_event("debug", " x%1 y%2 w%3 h%4 b%5 d%6", win_x, win_y, win_width, win_height, border_width, visual->depth); log_event("debug", " a.su%1, a.od%2", save_under, is_static_popup); // Create window handle.window = XCreateWindow( handle.display, _root_window, win_x, win_y, win_width, win_height, border_width, visual->depth, InputOutput, visual->visual, CWBorderPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask | CWColormap, &attr ); if (!handle.window) throw Exception("Unable to create the X11 window"); if (!desc.get_owner().is_null()) { DisplayWindow owner = desc.get_owner(); XSetTransientForHint(handle.display, handle.window, owner.get_handle().window); } // Setup the hidden cursor (Maybe this should be done only once when required) char data[64]; // 8x8 memset(data, 0, 64); XColor black_color; memset(&black_color, 0, sizeof(black_color)); cursor_bitmap = XCreateBitmapFromData(handle.display, handle.window, data, 8, 8); hidden_cursor = XCreatePixmapCursor(handle.display, cursor_bitmap, cursor_bitmap, &black_color, &black_color, 0,0); // Set title of window: set_title(desc.get_title()); { // Inform the window manager who we are, so it can kill us if we're not good for its universe. Atom atom; int32_t pid = getpid(); if (pid > 0) { atom = atoms.get_atom(handle.display, "_NET_WM_PID", False); XChangeProperty(handle.display, handle.window, atom, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &pid, 1); } char hostname[256]; if (gethostname(hostname, sizeof(hostname)) > -1) { hostname[255] = 0; atom = atoms.get_atom(handle.display, "WM_CLIENT_MACHINE", False); XChangeProperty(handle.display, handle.window, atom, XA_STRING, 8, PropModeReplace, (unsigned char *) hostname, strlen(hostname)); } } // Set-up window type/styling. // TODO Support more window types, broaden ClanLib window type support, etc. if (atoms["_NET_WM_WINDOW_TYPE"] != None) { Atom type = None; std::string name; if (desc.is_dialog()) { name = "_NET_WM_WINDOW_TYPE_DIALOG"; type = atoms[name]; } else if (desc.is_popup()) { if (is_static_popup) { name = "_NET_WM_WINDOW_TYPE_TOOLTIP"; type = atoms[name]; } else if (desc.has_caption()) // A pop-up with title bar -> utility { name = "_NET_WM_WINDOW_TYPE_UTILITY"; type = atoms[name]; } // else, a pop-up without a title bar -> popup-menu, combo, dropdown, tooltip, ... if (type == None) { name = "_NET_WM_WINDOW_TYPE_POPUP_MENU"; type = atoms[name]; } if (type == None) { name = "_NET_WM_WINDOW_TYPE_COMBO"; type = atoms[name]; } if (type == None) { name = "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"; type = atoms[name]; } } // else if (desc.is_normal()) // Fallback to normal window type if WM doesn't support what we want. if (type == None) { name = "_NET_WM_WINDOW_TYPE_NORMAL"; type = atoms[name]; } if (type != None) // Ensure selected type exists. { XChangeProperty(handle.display, handle.window, atoms["_NET_WM_WINDOW_TYPE"], XA_ATOM, 32, PropModeReplace, (unsigned char *)&type, 1); log_event("debug", "clan::X11Window::create(): Creating window of type '%1'.", name); } else { log_event("debug", "clan::X11Window::create(): Failed to find a suitable window type."); } } else { log_event("debug", "clan::X11Window::create(): _NET_WM_WINDOW_TYPE does not exist."); } // Set size hints XSetWMNormalHints(handle.display, handle.window, size_hints); { // Subscribe to WM events. Atom protocol = atoms["WM_DELETE_WINDOW"]; Status result = XSetWMProtocols(handle.display, handle.window, &protocol, 1); if (result == 0) log_event("debug", "clan::X11Window::create(): Failed to set WM_PROTOCOLS."); } { // Make auto-repeat keys detectable. Bool supports_detectable_autorepeat; XkbSetDetectableAutoRepeat(handle.display, True, &supports_detectable_autorepeat); } { // Make window full-screen if requested. if (atoms["_NET_WM_STATE"] == None && atoms["_NET_WM_STATE_FULLSCREEN"]) { fullscreen = false; log_event("debug", "clan::X11Window: Fullscreen not supported by WM."); } else { fullscreen = desc.is_fullscreen(); } if (fullscreen) { Atom state = atoms["_NET_WM_STATE_FULLSCREEN"]; XChangeProperty(handle.display, handle.window, atoms["_NET_WM_STATE"], XA_ATOM, 32, PropModeReplace, (unsigned char *)&state, 1); } } update_frame_extents(); auto new_client_area = desc.get_position_client_area() // supplied position is at ? client area : window area; ? Rect::xywh(win_x, win_y, win_width, win_height) : Rect::xywh(win_x + frame_extents.left, win_y + frame_extents.right, win_width, win_height) ; process_window_resize(new_client_area); // Set window visibility if (desc.is_visible()) { show(false); } // Setup the clipboard clipboard.setup(); // Go looking for joysticks: setup_joysticks(); } void X11Window::update_frame_extents() { frame_extents = Rect { border_width, border_width, border_width, border_width }; if (atoms["_NET_FRAME_EXTENTS"] == None) return; // Request frame extents from WM. if (atoms["_NET_REQUEST_FRAME_EXTENTS"] != None) { XEvent event; memset(&event, 0, sizeof(event)); event.type = ClientMessage; event.xclient.window = handle.window; event.xclient.format = 32; event.xclient.message_type = atoms["_NET_REQUEST_FRAME_EXTENTS"]; XSendEvent(handle.display, RootWindow(handle.display, handle.screen), False, SubstructureNotifyMask | SubstructureRedirectMask, &event); int timer = 10; while(true) { if (timer < 0) { log_event("debug", "clan::X11Window: Your window manager has a broken _NET_REQUEST_FRAME_EXTENTS implementation."); break; } if (XCheckMaskEvent(handle.display, PropertyNotify, &event)) { break; } clan::System::sleep(5); timer--; } } unsigned long item_count; // _NET_FRAME_EXTENTS, left, right, top, bottom, CARDINAL[4]/32 unsigned char *data = atoms.get_property(handle.window, "_NET_FRAME_EXTENTS", item_count); if (data == NULL) return; if (item_count >= 4) { long *cardinal = (long *)data; frame_extents.left = cardinal[0]; frame_extents.right = cardinal[1]; frame_extents.top = cardinal[2]; frame_extents.bottom = cardinal[3]; } XFree(data); }
bool wxTopLevelWindowGTK::Show( bool show ) { wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") ); bool deferShow = show && !m_isShown && m_deferShow; if (deferShow) { deferShow = gs_requestFrameExtentsStatus != 2 && m_deferShowAllowed && !gtk_widget_get_realized(m_widget); if (deferShow) { deferShow = g_signal_handler_find(m_widget, GSignalMatchType(G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA), g_signal_lookup("property_notify_event", GTK_TYPE_WIDGET), 0, NULL, NULL, this) != 0; } GdkScreen* screen = NULL; if (deferShow) { #ifdef GDK_WINDOWING_X11 screen = gtk_widget_get_screen(m_widget); GdkAtom atom = gdk_atom_intern("_NET_REQUEST_FRAME_EXTENTS", false); deferShow = gdk_x11_screen_supports_net_wm_hint(screen, atom) != 0; #else deferShow = false; #endif // If _NET_REQUEST_FRAME_EXTENTS not supported, don't allow changes // to m_decorSize, it breaks saving/restoring window size with // GetSize()/SetSize() because it makes window bigger between each // restore and save. m_updateDecorSize = deferShow; } m_deferShow = deferShow; } if (deferShow) { // Initial show. If WM supports _NET_REQUEST_FRAME_EXTENTS, defer // calling gtk_widget_show() until _NET_FRAME_EXTENTS property // notification is received, so correct frame extents are known. // This allows resizing m_widget to keep the overall size in sync with // what wxWidgets expects it to be without an obvious change in the // window size immediately after it becomes visible. // Realize m_widget, so m_widget->window can be used. Realizing normally // causes the widget tree to be size_allocated, which generates size // events in the wrong order. However, the size_allocates will not be // done if the allocation is not the default (1,1). GtkAllocation alloc; gtk_widget_get_allocation(m_widget, &alloc); const int alloc_width = alloc.width; if (alloc_width == 1) { alloc.width = 2; gtk_widget_set_allocation(m_widget, &alloc); } gtk_widget_realize(m_widget); if (alloc_width == 1) { alloc.width = 1; gtk_widget_set_allocation(m_widget, &alloc); } #ifdef GDK_WINDOWING_X11 // send _NET_REQUEST_FRAME_EXTENTS XClientMessageEvent xevent; memset(&xevent, 0, sizeof(xevent)); xevent.type = ClientMessage; GdkWindow* window = gtk_widget_get_window(m_widget); xevent.window = gdk_x11_drawable_get_xid(window); xevent.message_type = gdk_x11_atom_to_xatom_for_display( gdk_drawable_get_display(window), gdk_atom_intern("_NET_REQUEST_FRAME_EXTENTS", false)); xevent.format = 32; Display* display = gdk_x11_drawable_get_xdisplay(window); XSendEvent(display, DefaultRootWindow(display), false, SubstructureNotifyMask | SubstructureRedirectMask, (XEvent*)&xevent); #endif // GDK_WINDOWING_X11 if (gs_requestFrameExtentsStatus == 0) { // if WM does not respond to request within 1 second, // we assume support for _NET_REQUEST_FRAME_EXTENTS is not working m_netFrameExtentsTimerId = g_timeout_add(1000, request_frame_extents_timeout, this); } // defer calling gtk_widget_show() m_isShown = true; return true; } if (show && !gtk_widget_get_realized(m_widget)) { // size_allocate signals occur in reverse order (bottom to top). // Things work better if the initial wxSizeEvents are sent (from the // top down), before the initial size_allocate signals occur. wxSizeEvent event(GetSize(), GetId()); event.SetEventObject(this); HandleWindowEvent(event); } bool change = base_type::Show(show); if (change && !show) { // make sure window has a non-default position, so when it is shown // again, it won't be repositioned by WM as if it were a new window // Note that this must be done _after_ the window is hidden. gtk_window_move((GtkWindow*)m_widget, m_x, m_y); } return change; }
void GLWindow::initWindow(const char* windowName,bool decorate) { /* Check if the window's screen matches the context's: */ if(screen!=context->getScreen()) Misc::throwStdErr("GLWindow: OpenGL contexts cannot be shared between screens %d and %d on display %s",screen,context->getScreen(),context->getDisplayName()); /* Get a handle to the root window: */ root=RootWindow(context->getDisplay(),screen); /* Create an X colormap (visual might not be default): */ colorMap=XCreateColormap(context->getDisplay(),root,context->getVisual(),AllocNone); /* Create an X window with the selected visual: */ XSetWindowAttributes swa; swa.colormap=colorMap; swa.border_pixel=0; swa.override_redirect=False; if(fullscreen) // Create a fullscreen window { windowPos.origin[0]=0; windowPos.origin[1]=0; windowPos.size[0]=DisplayWidth(context->getDisplay(),screen); windowPos.size[1]=DisplayHeight(context->getDisplay(),screen); // decorate=false; swa.override_redirect=True; } swa.event_mask=PointerMotionMask|ButtonPressMask|ButtonReleaseMask|KeyPressMask|KeyReleaseMask|ExposureMask|StructureNotifyMask; unsigned long attributeMask=CWBorderPixel|CWColormap|CWOverrideRedirect|CWEventMask; window=XCreateWindow(context->getDisplay(),root, windowPos.origin[0],windowPos.origin[1],windowPos.size[0],windowPos.size[1], 0,context->getDepth(),InputOutput,context->getVisual(),attributeMask,&swa); XSetStandardProperties(context->getDisplay(),window,windowName,windowName,None,0,0,0); if(!decorate&&!fullscreen) { /******************************************************************* Ask the window manager not to decorate this window: *******************************************************************/ /* Create and fill in window manager hint structure inherited from Motif: */ struct MotifHints // Structure to pass hints to window managers { /* Elements: */ public: Misc::UInt32 flags; Misc::UInt32 functions; Misc::UInt32 decorations; Misc::SInt32 inputMode; Misc::UInt32 status; } hints; hints.flags=2U; // Only change decorations bit hints.functions=0U; hints.decorations=0U; hints.inputMode=0; hints.status=0U; /* Get the X atom to set hint properties: */ Atom hintProperty=XInternAtom(context->getDisplay(),"_MOTIF_WM_HINTS",True); if(hintProperty!=None) { /* Set the window manager hint property: */ XChangeProperty(context->getDisplay(),window,hintProperty,hintProperty,32,PropModeReplace,reinterpret_cast<unsigned char*>(&hints),5); } else Misc::userError("GLWindow::GLWindow: Unable to disable window decorations"); } if(fullscreen) { /* Get relevant window manager protocol atoms: */ Atom netwmBypassCompositorAtom=XInternAtom(context->getDisplay(),"_NET_WM_BYPASS_COMPOSITOR",True); if(netwmBypassCompositorAtom!=None) { /* Ask the window manager to let this window bypass the compositor: */ XEvent bypassCompositorEvent; memset(&bypassCompositorEvent,0,sizeof(XEvent)); bypassCompositorEvent.xclient.type=ClientMessage; bypassCompositorEvent.xclient.serial=0; bypassCompositorEvent.xclient.send_event=True; bypassCompositorEvent.xclient.display=context->getDisplay(); bypassCompositorEvent.xclient.window=window; bypassCompositorEvent.xclient.message_type=netwmBypassCompositorAtom; bypassCompositorEvent.xclient.format=32; bypassCompositorEvent.xclient.data.l[0]=1; // Bypass compositor XSendEvent(context->getDisplay(),RootWindow(context->getDisplay(),screen),False,SubstructureRedirectMask|SubstructureNotifyMask,&bypassCompositorEvent); XFlush(context->getDisplay()); } else Misc::userError("GLWindow::GLWindow: Unable to bypass desktop compositor"); } /* Initiate window manager communication: */ wmProtocolsAtom=XInternAtom(context->getDisplay(),"WM_PROTOCOLS",False); wmDeleteWindowAtom=XInternAtom(context->getDisplay(),"WM_DELETE_WINDOW",False); XSetWMProtocols(context->getDisplay(),window,&wmDeleteWindowAtom,1); /* Display the window on the screen: */ XMapWindow(context->getDisplay(),window); /* Flush the X queue in case there are events in the receive queue from opening a previous window: */ XFlush(context->getDisplay()); /* Process events up until the first Expose event to determine the initial window position and size: */ bool receivedConfigureNotify=false; int winX=0,winY=0; while(true) { XEvent event; XWindowEvent(context->getDisplay(),window,ExposureMask|StructureNotifyMask,&event); if(event.type==ConfigureNotify) { /* Retrieve the window position and size: */ winX=event.xconfigure.x; winY=event.xconfigure.y; windowPos.size[0]=event.xconfigure.width; windowPos.size[1]=event.xconfigure.height; receivedConfigureNotify=true; } else if(event.type==Expose) { /* Put the event back into the queue: */ XPutBackEvent(context->getDisplay(),&event); /* We're done here: */ break; } } if(receivedConfigureNotify) { /********************************************************************* Since modern window managers ignore window positions when opening windows, we now need to move the window to its requested position. Fix suggested by William Sherman. *********************************************************************/ if(decorate) { /* As it so happens, the initial window position is this window's offset inside its parent, so we can use that to calculate the parent position: */ XMoveWindow(context->getDisplay(),window,windowPos.origin[0]-winX,windowPos.origin[1]-winY); } else { /* Move the window's top-left corner to the requested position: */ XMoveWindow(context->getDisplay(),window,windowPos.origin[0],windowPos.origin[1]); } /* Wait for the final ConfigureNotify event to determine the final window position and size: */ while(true) { XEvent event; XWindowEvent(context->getDisplay(),window,StructureNotifyMask,&event); if(event.type==ConfigureNotify) { /* Retrieve the final window position and size: */ windowPos.origin[0]=event.xconfigure.x; windowPos.origin[1]=event.xconfigure.y; windowPos.size[0]=event.xconfigure.width; windowPos.size[1]=event.xconfigure.height; break; } } } if(fullscreen) { /* Grab pointer and keyboard: */ XGrabPointer(context->getDisplay(),window,True,0,GrabModeAsync,GrabModeAsync,None,None,CurrentTime); XGrabKeyboard(context->getDisplay(),window,True,GrabModeAsync,GrabModeAsync,CurrentTime); } /* Initialize the OpenGL context: */ context->init(window); /* Query needed GLX extension entry points: */ glXSwapIntervalEXTProc=GLExtensionManager::getFunction<PFNGLXSWAPINTERVALEXTPROC>("glXSwapIntervalEXT"); glXWaitVideoSyncSGIProc=GLExtensionManager::getFunction<PFNGLXWAITVIDEOSYNCSGIPROC>("glXWaitVideoSyncSGI"); glXDelayBeforeSwapNVProc=GLExtensionManager::getFunction<PFNGLXDELAYBEFORESWAPNVPROC>("glXDelayBeforeSwapNV"); }
Bool wsXDNDProcessClientMessage(wsTWindow* wnd, XClientMessageEvent *event) { /* test */ /*{ char * name = XGetAtomName(wsDisplay, event->message_type); printf("Got %s\n",name); XFree(name); }*/ if (event->message_type == _XA_XdndEnter) { Atom ok = XInternAtom(wsDisplay, "text/uri-list", False); atom_support = None; if ((event->data.l[1] & 1) == 0){ int index; for(index = 0; index <= 2 ; index++){ if (event->data.l[2+index] == ok) { atom_support = ok; } } if (atom_support == None) { mp_msg( MSGT_GPLAYER,MSGL_WARN,MSGTR_WS_NotAFile ); } } else { /* need to check the whole list here */ unsigned long ret_left = 1; int offset = 0; Atom* ret_buff; Atom ret_type; int ret_format; unsigned long ret_items; /* while there is data left...*/ while(ret_left && atom_support == None){ XGetWindowProperty(wsDisplay,event->data.l[0],_XA_XdndTypeList, offset,256,False,XA_ATOM,&ret_type, &ret_format,&ret_items,&ret_left, (unsigned char**)&ret_buff); /* sanity checks...*/ if(ret_buff == NULL || ret_type != XA_ATOM || ret_format != 8*sizeof(Atom)){ XFree(ret_buff); break; } /* now chek what we've got */ { int i; for(i=0; i<ret_items; i++){ if(ret_buff[i] == ok){ atom_support = ok; break; } } } /* maybe next time ... */ XFree(ret_buff); offset += 256; } } return True; } if (event->message_type == _XA_XdndLeave) { return True; } if (event->message_type == _XA_XdndDrop) { if (event->data.l[0] != XGetSelectionOwner(wsDisplay, _XA_XdndSelection)){ puts("Wierd selection owner... QT?"); } if (atom_support != None) { XConvertSelection(wsDisplay, _XA_XdndSelection, atom_support, _XA_XdndSelection, event->window, CurrentTime); } return True; } if (event->message_type == _XA_XdndPosition) { Window srcwin = event->data.l[0]; if (atom_support == None){ return True; } /* send response */ { XEvent xevent; memset (&xevent, 0, sizeof(xevent)); xevent.xany.type = ClientMessage; xevent.xany.display = wsDisplay; xevent.xclient.window = srcwin; xevent.xclient.message_type = _XA_XdndStatus; xevent.xclient.format = 32; XDND_STATUS_TARGET_WIN (&xevent) = event->window; XDND_STATUS_WILL_ACCEPT_SET (&xevent, True); XDND_STATUS_WANT_POSITION_SET(&xevent, True); /* actually need smth real here */ XDND_STATUS_RECT_SET(&xevent, 0, 0, 1024,768); XDND_STATUS_ACTION(&xevent) = _XA_XdndActionCopy; XSendEvent(wsDisplay, srcwin, 0, 0, &xevent); } return True; } return False; }
bool Gui::GUIApplicationNativeEventAware::x11EventFilter(XEvent *event) { #ifdef SPNAV_FOUND /* First we check if we have a motion flush event: - If there are unprocessed motion events we are in a flooding situation. In that case we wait with generating a Spaceball event. - A motion event counter of 0 indicates that FreeCAD is ready to process the event. A Spaceball event, using the saved motion data, is posted. */ static Display* display = QX11Info::display(); static Atom motion_flush_event = XInternAtom(display, "FCMotionFlushEvent", false); static int nMotionEvents = 0; QWidget *currentWidget = this->focusWidget(); if (!currentWidget) currentWidget = mainWindow; if (event->type == ClientMessage) { Atom message_type = event->xclient.message_type; if (message_type == motion_flush_event) { nMotionEvents--; if (nMotionEvents == 0) { importSettings(); Spaceball::MotionEvent *motionEvent = new Spaceball::MotionEvent(); motionEvent->setTranslations(motionDataArray[0], motionDataArray[1], motionDataArray[2]); motionEvent->setRotations(motionDataArray[3], motionDataArray[4], motionDataArray[5]); this->postEvent(currentWidget, motionEvent); } return true; } // XEvent: motion_flush_event } // XEvent: ClientMessage /* From here on we deal with spacenav events only: - motion: The event data is saved and a self addressed flush event is sent through the window system (XEvent). In the case of an event flooding, the motion data is added up. - button: A Spaceball event is posted (QInputEvent). */ spnav_event navEvent; if (!spnav_x11_event(event, &navEvent)) return false; if (navEvent.type == SPNAV_EVENT_MOTION) { /* If the motion data of the preceding event has not been processed through posting an Spaceball event (flooding situation), the motion data provided by the incoming event is added to the saved data. */ int dx, dy, dz, drx, dry, drz; if (nMotionEvents == 0) { dx = 0; dy = 0; dz = 0; drx = 0; dry = 0; drz = 0; } else { dx = motionDataArray[0]; dy = motionDataArray[1]; dz = motionDataArray[2]; drx = motionDataArray[3]; dry = motionDataArray[4]; drz = motionDataArray[5]; } motionDataArray[0] = navEvent.motion.x; motionDataArray[1] = navEvent.motion.y; motionDataArray[2] = navEvent.motion.z; motionDataArray[3] = navEvent.motion.rx; motionDataArray[4] = navEvent.motion.ry; motionDataArray[5] = navEvent.motion.rz; if (!setOSIndependentMotionData()) return false; motionDataArray[0] += dx; motionDataArray[1] += dy; motionDataArray[2] += dz; motionDataArray[3] += drx; motionDataArray[4] += dry; motionDataArray[5] += drz; /* Send a self addressed flush event through the window system. This will trigger a Spaceball event if FreeCAD is ready to do so. */ nMotionEvents++; XClientMessageEvent flushEvent; flushEvent.display = display; flushEvent.window = event->xclient.window; flushEvent.type = ClientMessage; flushEvent.format = 8; flushEvent.message_type = motion_flush_event; XSendEvent (display, flushEvent.window, False, 0, (XEvent*)&flushEvent); // siehe spnavd, False, 0 return true; } if (navEvent.type == SPNAV_EVENT_BUTTON) { Spaceball::ButtonEvent *buttonEvent = new Spaceball::ButtonEvent(); buttonEvent->setButtonNumber(navEvent.button.bnum); if (navEvent.button.press) buttonEvent->setButtonStatus(Spaceball::BUTTON_PRESSED); else buttonEvent->setButtonStatus(Spaceball::BUTTON_RELEASED); this->postEvent(currentWidget, buttonEvent); return true; } Base::Console().Log("Unknown spaceball event\n"); return true; #else Q_UNUSED(event); return false; #endif // SPNAV_FOUND }
void Frame::init() { maximized = false; set_state(1); state = "WithdrawnState"; shaped = false; XSelectInput(QX11Info::display(), winId(), KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | KeymapStateMask | ButtonMotionMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask | FocusChangeMask | VisibilityChangeMask | ExposureMask | StructureNotifyMask | SubstructureRedirectMask | SubstructureNotifyMask); XSetWindowAttributes at; at.event_mask = ColormapChangeMask|PropertyChangeMask; XChangeWindowAttributes(QX11Info::display(), c_win, CWEventMask, &at); XGrabServer(QX11Info::display()); // get the client geometry get_client_geometry(); // get the client hints get_wm_hints(); // get the client normal hints get_wm_normal_hints(); // get the client prot get_wm_protocols(); // get the client icon to show on header get_icon(); // get the client name get_wm_name(); // set the frame geometry set_frame_geometry(); // set the window modality set_window_modality(); shaped = query_shape(); if (shaped) reshape(); XSetWindowBorderWidth(QX11Info::display(), c_win, 0); //client XSetWindowBorderWidth(QX11Info::display(), winId(), 0); //frame // *** THE MOST IMPORTANT FUNCTION *** // reparent client with frame XReparentWindow(QX11Info::display(), c_win, winId(), lateral_bdr_width, top_bdr_height); qDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"; qDebug() << "Reparent Client:" << c_win << "with Frame:" << winId() << "- Name:" << cl_name(); qDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"; XAddToSaveSet(QX11Info::display(), c_win); // move and resize client XMoveResizeWindow(QX11Info::display(), c_win, lateral_bdr_width, top_bdr_height+3, client_w, client_h); //if the frame is too large, maximize it if (frame_w >= QApplication::desktop()->width()-20 || frame_h >= QApplication::desktop()->height()-40) { maximize_it(); } else // normal size { // move the frame in desktop center and resize move((QApplication::desktop()->width()/2)-(frame_w/2), (QApplication::desktop()->height()/2)-(frame_h/2)); resize(frame_w, frame_h); } qDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"; qDebug() << "Frame_x:" << frame_x << "Frame_y:" << frame_y << "Frame_w:" << frame_w << "Frame_h:" << frame_h; qDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << "\n"; if (frame_type != "Splash") // Splash frame have no header and no border { // create frame borders/header create_borders(); // set the header pixmap set_inactive(); splash = false; } else { qDebug() << "Frame:" << winId() << "Name:" << wm_name << "is Splash type"; splash = true; } // send _NET_ACTIVE_WINDOW property Atom _net_active_window = XInternAtom(QX11Info::display(), "_NET_ACTIVE_WINDOW", False); XClientMessageEvent xev; xev.type = ClientMessage; xev.window = c_win; xev.message_type = _net_active_window; xev.format = 32; xev.data.l[0] = 1; // from application xev.data.l[1] = CurrentTime; xev.data.l[2] = 0; XSendEvent(QX11Info::display(), QApplication::desktop()->winId(), False, StructureNotifyMask, (XEvent *)&xev); // map client XMapWindow(QX11Info::display(), c_win); XSync(QX11Info::display(), false); XUngrabServer(QX11Info::display()); // show frame show(); }
Status XReconfigureWMWindow ( register Display *dpy, Window w, int screen, unsigned int mask, XWindowChanges *changes) { XConfigureRequestEvent ev; Window root = RootWindow (dpy, screen); _XAsyncHandler async; _XAsyncErrorState async_state; /* * Only need to go through the trouble if we are actually changing the * stacking mode. */ if (!(mask & CWStackMode)) { XConfigureWindow (dpy, w, mask, changes); return True; } /* * We need to inline XConfigureWindow and XSync so that everything is done * while the display is locked. */ LockDisplay(dpy); /* * XConfigureWindow (dpy, w, mask, changes); */ { unsigned long values[7]; register unsigned long *value = values; long nvalues; register xConfigureWindowReq *req; GetReq(ConfigureWindow, req); async_state.min_sequence_number = dpy->request; async_state.max_sequence_number = dpy->request; async_state.error_code = BadMatch; async_state.major_opcode = X_ConfigureWindow; async_state.minor_opcode = 0; async_state.error_count = 0; async.next = dpy->async_handlers; async.handler = _XAsyncErrorHandler; async.data = (XPointer)&async_state; dpy->async_handlers = &async; req->window = w; mask &= AllMaskBits; req->mask = mask; if (mask & CWX) *value++ = changes->x; if (mask & CWY) *value++ = changes->y; if (mask & CWWidth) *value++ = changes->width; if (mask & CWHeight) *value++ = changes->height; if (mask & CWBorderWidth) *value++ = changes->border_width; if (mask & CWSibling) *value++ = changes->sibling; if (mask & CWStackMode) *value++ = changes->stack_mode; req->length += (nvalues = value - values); nvalues <<= 2; /* watch out for macros... */ Data32 (dpy, (long *) values, nvalues); } /* * XSync (dpy, 0) */ { xGetInputFocusReply rep; register xReq *req; GetEmptyReq(GetInputFocus, req); (void) _XReply (dpy, (xReply *)&rep, 0, xTrue); } DeqAsyncHandler(dpy, &async); UnlockDisplay(dpy); SyncHandle(); /* * If the request succeeded, then everything is okay; otherwise, send event */ if (!async_state.error_count) return True; ev.type = ConfigureRequest; ev.window = w; ev.parent = root; ev.value_mask = (mask & AllMaskBits); ev.x = changes->x; ev.y = changes->y; ev.width = changes->width; ev.height = changes->height; ev.border_width = changes->border_width; ev.above = changes->sibling; ev.detail = changes->stack_mode; return (XSendEvent (dpy, root, False, SubstructureRedirectMask|SubstructureNotifyMask, (XEvent *)&ev)); }
void* cdr_viewer_grab(void* args) { struct CamGrab_t* my_args = (struct CamGrab_t*)args; int new_fd; //new connection on new_fd //char recvbuf[k_timestamp_len * 3]; XEvent event; Display *display = XOpenDisplay(0); /* magic to get GUI to run periodically */ event.type = KeyPress; event.xkey.keycode = 9; /* ESC */ event.xkey.state = 0; /* no Mod1Mask */ while(!cdr_viewer_threads_should_die) { // first connect back to seykhl new_fd = ClientConnect(k_Server, my_args->PortNumber); if (new_fd == -1) { // connection not made, so sleep and keep trying cdr_viewer_active = FALSE; usleep(10000); continue; } else //connection made { //cdr_viewer_active = TRUE; printf("Connected to %s on port %s\n", k_Server, my_args->PortNumber); } while(!cdr_viewer_threads_should_die && (new_fd != -1)) { //here's where we do the magic PointGrey_t2* PG = new PointGrey_t2; PG->new_fd = new_fd; Imlib_Image temp_img; int working; while (1) { cdr_viewer_active = TRUE; if (cdr_OpenCV_ReceiveFrame(PG) != 0) { close(PG->new_fd); cdr_viewer_active = FALSE; break; } //convert opencv to imlib for display in viewer temp_img = Convert_OpenCV_to_Imlib(PG); pthread_mutex_lock(&my_args->MostRecentLock); working = ((my_args->MostRecent) + 1) % k_ImgBufSize; pthread_mutex_unlock(&my_args->MostRecentLock); pthread_mutex_lock(&my_args->ImgArrayLock[working]); if (my_args->Set[working] == TRUE) { //clean up memory allocation imlib_context_set_image(*my_args->ImgArray[working]); imlib_free_image_and_decache(); } else { my_args->Set[working] = TRUE; } *my_args->ImgArray[working] = temp_img; pthread_mutex_unlock(&my_args->ImgArrayLock[working]); pthread_mutex_lock(&my_args->MostRecentLock); my_args->MostRecent = working; pthread_mutex_unlock(&my_args->MostRecentLock); XSendEvent(display, cdr_display_pane, FALSE, 0, &event); XFlush(display); } delete PG; printf("cdr_viewer: exiting from loop while(!cdr_viewer_threads_should_die && (new_fd != -1))\n"); break; } printf("closing new_fd\n"); close(new_fd); // accept loop doesn't need this } //do cleanup here printf("exiting cdr_viewer_grab\n"); return NULL; }
// functions not called from Scheme void* rover_server_grab(void* args) { struct CamGrab_t* my_args = (struct CamGrab_t*)args; int sockfd, new_fd; // listen on sock_fd, new connection on new_fd int cdr_sockfd, cdr_new_fd; //for commander images int retval; char recvbuf[k_timestamp_len * 3]; XEvent event; Display *display = XOpenDisplay(0); /* magic to get GUI to run periodically */ event.type = KeyPress; event.xkey.keycode = 9; /* ESC */ event.xkey.state = 0; /* no Mod1Mask */ sockfd = StartServer(my_args->PortNumber); // cv::VideoWriter output_video; // cv::Size vid_size = cv::Size(640,480); //**HARDCODED** for 640x480 video // int codec = CV_FOURCC('M','J','P','G'); // output_video.open(my_args->video_file_name, codec, 12.0, vid_size, true); printf("Opened video file %s\n", my_args->video_file_name); printf("server: waiting for image connection on port %s...\n", my_args->PortNumber); cdr_sockfd = StartServer(my_args->CdrPortNumber); printf("server: waiting for commander image connection on port %s...\n", my_args->CdrPortNumber); while(!grab_threads_should_die) { // main accept() loop usleep(10000); new_fd = AcceptConnection(sockfd); /* AcceptConnection set to non-blocking, so will spin here until it either gets a valid new_fd (and then goes into while loop below) or grab_threads_should_die becomes TRUE, which will cause the while loop (and function) to exit. */ if (new_fd != -1) { //receive and log start message into log file memset(recvbuf, 0 , sizeof(recvbuf)); retval = recv(new_fd, &recvbuf, sizeof(recvbuf), 0); if (retval < 0) { //what error handling??? printf("rover_server_grab recv retval = %d\n", retval); } else { fprintf(my_args->file_ptr, "%s\n", recvbuf); memset(recvbuf, 0 , sizeof(recvbuf)); } //try to connect to commander viewer // cdr_sockfd = StartServer(my_args->CdrPortNumber); // printf("server: waiting for commander image connection on port %s...\n", // my_args->CdrPortNumber); cdr_new_fd = AcceptConnection(cdr_sockfd); if (cdr_new_fd != -1) { //connection successful cdr_viewer_active = TRUE; printf("Commander viewer CONNECTED on port %s\n", my_args->CdrPortNumber); } else { //connection failed cdr_viewer_active = FALSE; printf("Commander image connection failed for port %s\n", my_args->CdrPortNumber); } } while(!grab_threads_should_die && (new_fd != -1)) { //here's where we do the magic PointGrey_t2* PG = new PointGrey_t2; PG->new_fd = new_fd; PG->cdr_new_fd = cdr_new_fd; Imlib_Image temp_img; int working; while (1) { if (OpenCV_ReceiveFrame(PG, my_args->file_ptr) != 0) { close(PG->cdr_new_fd); cdr_viewer_active = FALSE; // printf("before close cdr_sockfd = %d\n", cdr_sockfd); // close(cdr_sockfd); // printf("after close cdr_sockfd = %d\n", cdr_sockfd); break; } //write frame to output video file my_args->output_video->write(PG->uncompressedImage); //send to commander viewer here?? //convert opencv to imlib for display in viewer temp_img = Convert_OpenCV_to_Imlib(PG); pthread_mutex_lock(&my_args->MostRecentLock); working = ((my_args->MostRecent) + 1) % k_ImgBufSize; pthread_mutex_unlock(&my_args->MostRecentLock); pthread_mutex_lock(&my_args->ImgArrayLock[working]); if (my_args->Set[working] == TRUE) { //clean up memory allocation imlib_context_set_image(*my_args->ImgArray[working]); imlib_free_image_and_decache(); } else { my_args->Set[working] = TRUE; } *my_args->ImgArray[working] = temp_img; pthread_mutex_unlock(&my_args->ImgArrayLock[working]); pthread_mutex_lock(&my_args->MostRecentLock); my_args->MostRecent = working; pthread_mutex_unlock(&my_args->MostRecentLock); XSendEvent(display, display_pane, FALSE, 0, &event); XFlush(display); } delete PG; printf("exiting from loop after AcceptConnection\n"); break; } if (new_fd != -1) {//receive and log stop message into log file //memset(recvbuf, 0 , sizeof(recvbuf)); retval = recv(new_fd, &recvbuf, sizeof(recvbuf), 0); if (retval <= 0) { //what error handling??? printf("rover_server_grab recv (end) retval = %d\n", retval); } else fprintf(my_args->file_ptr, "%s\n", recvbuf); } close(new_fd); // accept loop doesn't need this } //do cleanup here close(sockfd); printf("sockfd closed\n"); return NULL; }
gboolean _gdk_x11_window_simulate_key (GdkWindow *window, gint x, gint y, guint keyval, GdkModifierType modifiers, GdkEventType key_pressrelease) { GdkScreen *screen; GdkKeymapKey *keys = NULL; gboolean success; gint n_keys = 0; XKeyEvent xev = { 0, /* type */ 0, /* serial */ 1, /* send_event */ }; g_return_val_if_fail (key_pressrelease == GDK_KEY_PRESS || key_pressrelease == GDK_KEY_RELEASE, FALSE); g_return_val_if_fail (window != NULL, FALSE); if (!GDK_WINDOW_IS_MAPPED (window)) return FALSE; screen = gdk_window_get_screen (window); if (x < 0 && y < 0) { x = window->width / 2; y = window->height / 2; } /* Convert to impl coordinates */ x = x + window->abs_x; y = y + window->abs_y; xev.type = key_pressrelease == GDK_KEY_PRESS ? KeyPress : KeyRelease; xev.display = GDK_WINDOW_XDISPLAY (window); xev.window = GDK_WINDOW_XID (window); xev.root = RootWindow (xev.display, GDK_X11_SCREEN (screen)->screen_num); xev.subwindow = 0; xev.time = 0; xev.x = MAX (x, 0); xev.y = MAX (y, 0); xev.x_root = 0; xev.y_root = 0; xev.state = modifiers; xev.keycode = 0; success = gdk_keymap_get_entries_for_keyval (gdk_keymap_get_for_display (gdk_window_get_display (window)), keyval, &keys, &n_keys); success &= n_keys > 0; if (success) { gint i; for (i = 0; i < n_keys; i++) if (keys[i].group == 0 && (keys[i].level == 0 || keys[i].level == 1)) { xev.keycode = keys[i].keycode; if (keys[i].level == 1) { /* Assume shift takes us to level 1 */ xev.state |= GDK_SHIFT_MASK; } break; } if (i >= n_keys) /* no match for group==0 and level==0 or 1 */ xev.keycode = keys[0].keycode; } g_free (keys); if (!success) return FALSE; gdk_x11_display_error_trap_push (GDK_WINDOW_DISPLAY (window)); xev.same_screen = XTranslateCoordinates (xev.display, xev.window, xev.root, xev.x, xev.y, &xev.x_root, &xev.y_root, &xev.subwindow); if (!xev.subwindow) xev.subwindow = xev.window; success &= xev.same_screen; if (x >= 0 && y >= 0) success &= 0 != XWarpPointer (xev.display, None, xev.window, 0, 0, 0, 0, xev.x, xev.y); success &= 0 != XSendEvent (xev.display, xev.window, True, key_pressrelease == GDK_KEY_PRESS ? KeyPressMask : KeyReleaseMask, (XEvent*) &xev); XSync (xev.display, False); success &= 0 == gdk_x11_display_error_trap_pop (GDK_WINDOW_DISPLAY (window)); return success; }
Bool wsXDNDProcessSelection(wsTWindow* wnd, XEvent *event) { Atom ret_type; int ret_format; unsigned long ret_items; unsigned long remain_byte; char * delme; XEvent xevent; Window selowner = XGetSelectionOwner(wsDisplay,_XA_XdndSelection); XGetWindowProperty(wsDisplay, event->xselection.requestor, event->xselection.property, 0, 65536, True, atom_support, &ret_type, &ret_format, &ret_items, &remain_byte, (unsigned char **)&delme); /*send finished*/ memset (&xevent, 0, sizeof(xevent)); xevent.xany.type = ClientMessage; xevent.xany.display = wsDisplay; xevent.xclient.window = selowner; xevent.xclient.message_type = _XA_XdndFinished; xevent.xclient.format = 32; XDND_FINISHED_TARGET_WIN(&xevent) = wnd->WindowID; XSendEvent(wsDisplay, selowner, 0, 0, &xevent); if (!delme){ mp_msg( MSGT_GPLAYER,MSGL_WARN,MSGTR_WS_DDNothing ); return False; } { /* Handle dropped files */ char * retain = delme; char * files[MAX_DND_FILES]; int num = 0; while(retain < delme + ret_items) { if (!strncmp(retain,"file:",5)) { /* add more 2 chars while removing 5 is harmless */ retain+=5; } /* add the "retain" to the list */ files[num++]=retain; /* now check for special characters */ { int newone = 0; while(retain < (delme + ret_items)){ if(*retain == '\r' || *retain == '\n'){ *retain=0; newone = 1; } else { if (newone) break; } retain++; } } if (num >= MAX_DND_FILES) break; } /* Handle the files */ if(wnd->DandDHandler){ wnd->DandDHandler(num,files); } } free(delme); return True; }
/* Create auxiliary (toplevel) windows with the current visual */ static void create_aux_windows(_THIS) { int x = 0, y = 0; char classname[1024]; XSetWindowAttributes xattr; XWMHints *hints; unsigned long app_event_mask; int def_vis = (SDL_Visual == DefaultVisual(SDL_Display, SDL_Screen)); /* Look up some useful Atoms */ WM_DELETE_WINDOW = XInternAtom(SDL_Display, "WM_DELETE_WINDOW", False); /* Don't create any extra windows if we are being managed */ if ( SDL_windowid ) { FSwindow = 0; WMwindow = SDL_strtol(SDL_windowid, NULL, 0); return; } if(FSwindow) XDestroyWindow(SDL_Display, FSwindow); #if SDL_VIDEO_DRIVER_X11_XINERAMA if ( use_xinerama ) { x = xinerama_info.x_org; y = xinerama_info.y_org; } #endif xattr.override_redirect = True; xattr.background_pixel = def_vis ? BlackPixel(SDL_Display, SDL_Screen) : 0; xattr.border_pixel = 0; xattr.colormap = SDL_XColorMap; FSwindow = XCreateWindow(SDL_Display, SDL_Root, x, y, 32, 32, 0, this->hidden->depth, InputOutput, SDL_Visual, CWOverrideRedirect | CWBackPixel | CWBorderPixel | CWColormap, &xattr); XSelectInput(SDL_Display, FSwindow, StructureNotifyMask); /* Tell KDE to keep the fullscreen window on top */ { XEvent ev; long mask; SDL_memset(&ev, 0, sizeof(ev)); ev.xclient.type = ClientMessage; ev.xclient.window = SDL_Root; ev.xclient.message_type = XInternAtom(SDL_Display, "KWM_KEEP_ON_TOP", False); ev.xclient.format = 32; ev.xclient.data.l[0] = FSwindow; ev.xclient.data.l[1] = CurrentTime; mask = SubstructureRedirectMask; XSendEvent(SDL_Display, SDL_Root, False, mask, &ev); } hints = NULL; if(WMwindow) { /* All window attributes must survive the recreation */ hints = XGetWMHints(SDL_Display, WMwindow); XDestroyWindow(SDL_Display, WMwindow); } /* Create the window for windowed management */ /* (reusing the xattr structure above) */ WMwindow = XCreateWindow(SDL_Display, SDL_Root, x, y, 32, 32, 0, this->hidden->depth, InputOutput, SDL_Visual, CWBackPixel | CWBorderPixel | CWColormap, &xattr); /* Set the input hints so we get keyboard input */ if(!hints) { hints = XAllocWMHints(); hints->input = True; hints->flags = InputHint; } XSetWMHints(SDL_Display, WMwindow, hints); XFree(hints); X11_SetCaptionNoLock(this, this->wm_title, this->wm_icon); app_event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask | PropertyChangeMask | StructureNotifyMask | KeymapStateMask; XSelectInput(SDL_Display, WMwindow, app_event_mask); /* Set the class hints so we can get an icon (AfterStep) */ get_classname(classname, sizeof(classname)); { XClassHint *classhints; classhints = XAllocClassHint(); if(classhints != NULL) { classhints->res_name = classname; classhints->res_class = classname; XSetClassHint(SDL_Display, WMwindow, classhints); XFree(classhints); } } /* Setup the communication with the IM server */ /* create_aux_windows may be called several times against the same Display. We should reuse the SDL_IM if one has been opened for the Display, so we should not simply reset SDL_IM here. */ #ifdef X_HAVE_UTF8_STRING if (SDL_X11_HAVE_UTF8) { /* Discard obsolete resources if any. */ if (SDL_IM != NULL && SDL_Display != XDisplayOfIM(SDL_IM)) { /* Just a double check. I don't think this code is ever executed. */ SDL_SetError("display has changed while an IM is kept"); if (SDL_IC) { XUnsetICFocus(SDL_IC); XDestroyIC(SDL_IC); SDL_IC = NULL; } XCloseIM(SDL_IM); SDL_IM = NULL; } /* Open an input method. */ if (SDL_IM == NULL) { char *old_locale = NULL, *old_modifiers = NULL; const char *p; size_t n; /* I'm not comfortable to do locale setup here. However, we need C library locale (and xlib modifiers) to be set based on the user's preference to use XIM, and many existing game programs doesn't take care of users' locale preferences, so someone other than the game program should do it. Moreover, ones say that some game programs heavily rely on the C locale behaviour, e.g., strcol()'s, and we can't change the C library locale. Given the situation, I couldn't find better place to do the job... */ /* Save the current (application program's) locale settings. */ p = setlocale(LC_ALL, NULL); if ( p ) { n = SDL_strlen(p)+1; old_locale = SDL_stack_alloc(char, n); if ( old_locale ) { SDL_strlcpy(old_locale, p, n); } } p = XSetLocaleModifiers(NULL); if ( p ) { n = SDL_strlen(p)+1; old_modifiers = SDL_stack_alloc(char, n); if ( old_modifiers ) { SDL_strlcpy(old_modifiers, p, n); } } /* Fetch the user's preferences and open the input method with them. */ setlocale(LC_ALL, ""); XSetLocaleModifiers(""); SDL_IM = XOpenIM(SDL_Display, NULL, classname, classname); /* Restore the application's locale settings so that we don't break the application's expected behaviour. */ if ( old_locale ) { /* We need to restore the C library locale first, since the interpretation of the X modifier may depend on it. */ setlocale(LC_ALL, old_locale); SDL_stack_free(old_locale); } if ( old_modifiers ) { XSetLocaleModifiers(old_modifiers); SDL_stack_free(old_modifiers); } } /* Create a new input context for the new window just created. */ if (SDL_IM == NULL) { SDL_SetError("no input method could be opened"); } else { if (SDL_IC != NULL) { /* Discard the old IC before creating new one. */ XUnsetICFocus(SDL_IC); XDestroyIC(SDL_IC); } /* Theoretically we should check the current IM supports PreeditNothing+StatusNothing style (i.e., root window method) before creating the IC. However, it is the bottom line method, and we supports any other options. If the IM didn't support root window method, the following call fails, and SDL falls back to pre-XIM keyboard handling. */ SDL_IC = pXCreateIC(SDL_IM, XNClientWindow, WMwindow, XNFocusWindow, WMwindow, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNResourceName, classname, XNResourceClass, classname, NULL); if (SDL_IC == NULL) { SDL_SetError("no input context could be created"); XCloseIM(SDL_IM); SDL_IM = NULL; } else { /* We need to receive X events that an IM wants and to pass them to the IM through XFilterEvent. The set of events may vary depending on the IM implementation and the options specified through various routes. Although unlikely, the xlib specification allows IM to change the event requirement with its own circumstances, it is safe to call SelectInput whenever we re-create an IC. */ unsigned long mask = 0; char *ret = pXGetICValues(SDL_IC, XNFilterEvents, &mask, NULL); if (ret != NULL) { XUnsetICFocus(SDL_IC); XDestroyIC(SDL_IC); SDL_IC = NULL; SDL_SetError("no input context could be created"); XCloseIM(SDL_IM); SDL_IM = NULL; } else { XSelectInput(SDL_Display, WMwindow, app_event_mask | mask); XSetICFocus(SDL_IC); } } } }
void qt_handle_xdnd_position( QWidget *w, const XEvent * xe, bool passive ) { const unsigned long *l = (const unsigned long *)xe->xclient.data.l; QPoint p( (l[2] & 0xffff0000) >> 16, l[2] & 0x0000ffff ); QWidget * c = find_child( w, p ); // changes p to to c-local coordinates if (!passive && checkEmbedded(c, xe)) return; if ( !c || !c->acceptDrops() && c->isDesktop() ) { return; } if ( l[0] != qt_xdnd_dragsource_xid ) { //qDebug( "xdnd drag position from unexpected source (%08lx not %08lx)", // l[0], qt_xdnd_dragsource_xid ); return; } if (l[3] != 0) { // timestamp from the source qt_xdnd_target_current_time = qt_x_user_time = l[3]; } XClientMessageEvent response; response.type = ClientMessage; response.window = qt_xdnd_dragsource_xid; response.format = 32; response.message_type = qt_xdnd_status; response.data.l[0] = w->winId(); response.data.l[1] = 0; // flags response.data.l[2] = 0; // x, y response.data.l[3] = 0; // w, h response.data.l[4] = 0; // action if ( !passive ) { // otherwise just reject while ( c && !c->acceptDrops() && !c->isTopLevel() ) { p = c->mapToParent( p ); c = c->parentWidget(); } QRect answerRect( c->mapToGlobal( p ), QSize( 1,1 ) ); QDragMoveEvent me( p ); QDropEvent::Action accepted_action = xdndaction_to_qtaction(l[4]); me.setAction(accepted_action); if ( c != qt_xdnd_current_widget ) { qt_xdnd_target_answerwas = FALSE; if ( qt_xdnd_current_widget ) { QDragLeaveEvent e; QApplication::sendEvent( qt_xdnd_current_widget, &e ); } if ( c->acceptDrops() ) { qt_xdnd_current_widget = c; qt_xdnd_current_position = p; QDragEnterEvent de( p ); de.setAction(accepted_action); QApplication::sendEvent( c, &de ); if ( de.isAccepted() ) { me.accept( de.answerRect() ); if ( !de.isActionAccepted() ) // only as a copy (move if we del) accepted_action = QDropEvent::Copy; else me.acceptAction(TRUE); } else { me.ignore( de.answerRect() ); } } } else { if ( qt_xdnd_target_answerwas ) { me.accept(); me.acceptAction(global_requested_action == global_accepted_action); } } if ( !c->acceptDrops() ) { qt_xdnd_current_widget = 0; answerRect = QRect( p, QSize( 1, 1 ) ); } else if ( xdndaction_to_qtaction(l[4]) < QDropEvent::Private ) { qt_xdnd_current_widget = c; qt_xdnd_current_position = p; QApplication::sendEvent( c, &me ); qt_xdnd_target_answerwas = me.isAccepted(); if ( me.isAccepted() ) { response.data.l[1] = 1; // yes if ( !me.isActionAccepted() ) // only as a copy (move if we del) accepted_action = QDropEvent::Copy; } else { response.data.l[0] = 0; } answerRect = me.answerRect().intersect( c->rect() ); } else { response.data.l[0] = 0; answerRect = QRect( p, QSize( 1, 1 ) ); } answerRect = QRect( c->mapToGlobal( answerRect.topLeft() ), answerRect.size() ); if ( answerRect.left() < 0 ) answerRect.setLeft( 0 ); if ( answerRect.right() > 4096 ) answerRect.setRight( 4096 ); if ( answerRect.top() < 0 ) answerRect.setTop( 0 ); if ( answerRect.bottom() > 4096 ) answerRect.setBottom( 4096 ); if ( answerRect.width() < 0 ) answerRect.setWidth( 0 ); if ( answerRect.height() < 0 ) answerRect.setHeight( 0 ); response.data.l[2] = (answerRect.x() << 16) + answerRect.y(); response.data.l[3] = (answerRect.width() << 16) + answerRect.height(); response.data.l[4] = qtaction_to_xdndaction(accepted_action); global_accepted_action = accepted_action; } // reset qt_xdnd_target_current_time = CurrentTime; QWidget * source = QWidget::find( qt_xdnd_dragsource_xid ); if ( source && source->isDesktop() && !source->acceptDrops() ) source = 0; if ( source ) qt_handle_xdnd_status( source, (const XEvent *)&response, passive ); else XSendEvent( QPaintDevice::x11AppDisplay(), qt_xdnd_dragsource_xid, False, NoEventMask, (XEvent*)&response ); }
// Danger: This function could delete "this" void X11Window::process_message(XEvent &event, X11Window *mouse_capture_window) { switch(event.type) { case ConfigureNotify: { // Resize or Move Rect new_client_area = (event.xany.send_event == 0) ? get_screen_position() : Rect::xywh( event.xconfigure.x + event.xconfigure.border_width, event.xconfigure.y + event.xconfigure.border_width, event.xconfigure.width, event.xconfigure.height ); process_window_resize(new_client_area); break; } case ClientMessage: { // handle window manager messages Atom WM_PROTOCOLS = atoms["WM_PROTOCOLS"]; if (WM_PROTOCOLS == None) { log_event("debug", "clan::X11Window::process_message: WM_PROTOCOLS not supported by WM."); break; } else if (event.xclient.message_type == WM_PROTOCOLS) { unsigned long protocol = event.xclient.data.l[0]; if (protocol == None) { log_event("debug", "clan::X11Window::process_message: WM_PROTOCOLS event protocol supplied is None."); break; } Atom WM_DELETE_WINDOW = atoms["WM_DELETE_WINDOW"]; Atom _NET_WM_PING = atoms["_NET_WM_PING"]; if (protocol == WM_DELETE_WINDOW && site) { (site->sig_window_close)(); } else if (protocol == _NET_WM_PING) { XSendEvent(handle.display, RootWindow(handle.display, handle.screen), False, SubstructureNotifyMask | SubstructureRedirectMask, &event); } } break; } case Expose: { // Window exposure repaint_request = true; break; } case FocusIn: if (site) (site->sig_got_focus)(); break; case FocusOut: if (site) { if (!has_focus()) // For an unknown reason, FocusOut is called when clicking on title bar of window { (site->sig_lost_focus)(); } } break; case PropertyNotify: { // Iconify, Maximized, ... if (!site) break; Atom _NET_WM_STATE = atoms["_NET_WM_STATE"]; Atom WM_STATE = atoms["WM_STATE"]; // legacy. if (_NET_WM_STATE != None && event.xproperty.atom == _NET_WM_STATE && event.xproperty.state == PropertyNewValue) { if (is_minimized()) { if (!minimized && site != nullptr) (site->sig_window_minimized)(); minimized = true; maximized = false; } else if (is_maximized()) { if (!maximized && site != nullptr) (site->sig_window_maximized)(); if (minimized && site != nullptr) { // generate resize events for minimized -> maximized transition Rectf rectf = get_geometry(); rectf.left /= pixel_ratio; rectf.top /= pixel_ratio; rectf.right /= pixel_ratio; rectf.bottom /= pixel_ratio; (site->sig_window_moved)(); if (site->func_window_resize) (site->func_window_resize)(rectf); if (callback_on_resized) callback_on_resized(); (site->sig_resize)(rectf.get_width(), rectf.get_height()); } minimized = false; maximized = true; } else { if ((minimized || maximized) && site != nullptr) (site->sig_window_restored)(); minimized = false; maximized = false; } } else if (WM_STATE != None && event.xproperty.atom == WM_STATE && event.xproperty.state == PropertyNewValue) { if (is_minimized()) { if (!minimized && site != nullptr) (site->sig_window_minimized)(); minimized = true; } else { if (minimized && site != nullptr) (site->sig_window_restored)(); minimized = false; } } break; } case KeyRelease: case KeyPress: if (get_keyboard_provider()) { get_keyboard_provider()->received_keyboard_input(keyboard, event.xkey); } break; case ButtonPress: case ButtonRelease: if (mouse_capture_window->get_mouse_provider() && event.xany.send_event==0) { if (callback_on_clicked) { // This callback is required for GL layered windows if (!callback_on_clicked(event.xbutton)) break; } if (this != mouse_capture_window) // This is so you can capture mouse events in another window, as if it was this window (Set by capture_mouse()) { Rect this_scr = client_area; Rect capture_scr = mouse_capture_window->client_area; event.xbutton.x += this_scr.left - capture_scr.left; event.xbutton.y += this_scr.top - capture_scr.top; } mouse_capture_window->get_mouse_provider()->received_mouse_input(mouse_capture_window->mouse, event.xbutton); } break; case MotionNotify: if (mouse_capture_window->get_mouse_provider() && event.xany.send_event == 0) { if (this != mouse_capture_window) // This is so you can capture mouse events in another window, as if it was this window (Set by capture_mouse()) { Rect this_scr = client_area; Rect capture_scr = mouse_capture_window->client_area; event.xmotion.x += this_scr.left - capture_scr.left; event.xmotion.y += this_scr.top - capture_scr.top; } mouse_capture_window->get_mouse_provider()->received_mouse_move(mouse_capture_window->mouse, event.xmotion); } break; case SelectionClear: // New clipboard selection owner clipboard.event_selection_clear(event.xselectionclear); break; case SelectionNotify: clipboard.event_selection_notify(); break; case SelectionRequest: // Clipboard requests clipboard.event_selection_request(event.xselectionrequest); break; default: break; } }
void* platform::getNativeWindow() { Window root; XSetWindowAttributes swa; XSetWindowAttributes xattr; Atom wm_state; XWMHints hints; XEvent xev; EGLConfig ecfg; EGLint num_config; Window win; Display* x_display = XOpenDisplay(NULL); assert(x_display); /* * X11 native display initialization */ x_display = XOpenDisplay(NULL); if ( x_display == NULL ) { return EGL_FALSE; } root = DefaultRootWindow(x_display); swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask; win = XCreateWindow( x_display, root, 0, 0, 640, 480, 0, CopyFromParent, InputOutput, CopyFromParent, CWEventMask, &swa ); xattr.override_redirect = false; XChangeWindowAttributes ( x_display, win, CWOverrideRedirect, &xattr ); hints.input = true; hints.flags = InputHint; XSetWMHints(x_display, win, &hints); // make the window visible on the screen XMapWindow (x_display, win); XStoreName (x_display, win, "foo"); // get identifiers for the provided atom name strings wm_state = XInternAtom (x_display, "_NET_WM_STATE", false); memset ( &xev, 0, sizeof(xev) ); xev.type = ClientMessage; xev.xclient.window = win; xev.xclient.message_type = wm_state; xev.xclient.format = 32; xev.xclient.data.l[0] = 1; xev.xclient.data.l[1] = false; XSendEvent ( x_display, DefaultRootWindow ( x_display ), false, SubstructureNotifyMask, &xev ); //(eEGLNativeWindowType) win; return (void*) win; }
int initX() { #if defined XORG_BUILD /////// the X11 part ////////////////////////////////////////////////////////////////// // in the first part the program opens a connection to the X11 window manager // x_display = XOpenDisplay ( NULL ); // open the standard display (the primary screen) if ( x_display == NULL ) { printf("cannot connect to X server\n"); return 1; } // Window root = DefaultRootWindow( x_display ); // get the root window (usually the whole screen) long x_screen = XDefaultScreen(x_display); Window root = RootWindow(x_display, x_screen); XSetWindowAttributes swa; swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask; xwin = XCreateWindow ( // create a window with the provided parameters x_display, root, 0, 0, 800, 480, 0, CopyFromParent, InputOutput, CopyFromParent, CWEventMask, &swa ); XSetWindowAttributes xattr; Atom atom; int one = 1; xattr.override_redirect = False; XChangeWindowAttributes ( x_display, xwin, CWOverrideRedirect, &xattr ); #if 0 atom = XInternAtom ( x_display, "_NET_WM_STATE_FULLSCREEN", True ); XChangeProperty ( x_display, win, XInternAtom ( x_display, "_NET_WM_STATE", True ), XA_ATOM, 32, PropModeReplace, (unsigned char*) &atom, 1 ); XChangeProperty ( x_display, win, XInternAtom ( x_display, "_HILDON_NON_COMPOSITED_WINDOW", True ), XA_INTEGER, 32, PropModeReplace, (unsigned char*) &one, 1); #endif XWMHints hints; hints.input = True; hints.flags = InputHint; XSetWMHints(x_display, xwin, &hints); XMapWindow ( x_display , xwin ); // make the window visible on the screen XStoreName ( x_display , xwin , "GL test" ); // give the window a name //// get identifiers for the provided atom name strings Atom wm_state = XInternAtom ( x_display, "_NET_WM_STATE", False ); Atom fullscreen = XInternAtom ( x_display, "_NET_WM_STATE_FULLSCREEN", False ); XEvent xev; memset ( &xev, 0, sizeof(xev) ); xev.type = ClientMessage; xev.xclient.window = xwin; xev.xclient.message_type = wm_state; xev.xclient.format = 32; xev.xclient.data.l[0] = 1; xev.xclient.data.l[1] = fullscreen; XSendEvent ( // send an event mask to the X-server x_display, DefaultRootWindow ( x_display ), False, SubstructureNotifyMask, &xev ); #endif }
/** * Filters through SDL_Events searching for clipboard requests from the X * server. * * @param evt The event to filter. */ static int widgetClipboardFilterX11(const SDL_Event *evt) { // We are only interested in window manager events if (evt->type == SDL_SYSWMEVENT) { XEvent xevent = evt->syswm.msg->event.xevent; // See if the event is a selection/clipboard request if (xevent.type == SelectionRequest) { // Get the request in question XSelectionRequestEvent *request = &xevent.xselectionrequest; // Generate a reply to the selection request XSelectionEvent reply; reply.type = SelectionNotify; reply.serial = xevent.xany.send_event; reply.send_event = True; reply.display = info.info.x11.display; reply.requestor = request->requestor; reply.selection = request->selection; reply.property = request->property; reply.target = None; reply.time = request->time; // They want to know what we can provide/offer if (request->target == XA_TARGETS) { Atom possibleTargets[] = { XA_STRING, XA_UTF8_STRING, XA_COMPOUND_TEXT }; XChangeProperty(info.info.x11.display, request->requestor, request->property, XA_ATOM, 32, PropModeReplace, (unsigned char *) possibleTargets, 3); } // They want a string (all we can provide) else if (request->target == XA_STRING || request->target == XA_UTF8_STRING || request->target == XA_COMPOUND_TEXT) { int len; char *xdata = XFetchBytes(info.info.x11.display, &len); XChangeProperty(info.info.x11.display, request->requestor, request->property, request->target, 8, PropModeReplace, (unsigned char *) xdata, len); XFree(xdata); } else { // Did not have what they wanted, so no property set reply.property = None; } // Dispatch the event XSendEvent(request->display, request->requestor, 0, NoEventMask, (XEvent *) &reply); XSync(info.info.x11.display, False); } } return 1; }
void handle_system_event(const SDL_Event& event) { XEvent& xev = event.syswm.msg->event.xevent; if (xev.type == SelectionRequest) { UseX x11; // Since wesnoth does not notify us of selections, // we set both selection + clipboard when copying. if ((xev.xselectionrequest.owner == x11->window()) && ((xev.xselectionrequest.selection == XA_PRIMARY) || (xev.xselectionrequest.selection == x11->XA_CLIPBOARD()))) { XEvent responseEvent; responseEvent.xselection.type = SelectionNotify; responseEvent.xselection.display = x11->dpy(); responseEvent.xselection.requestor = xev.xselectionrequest.requestor; responseEvent.xselection.selection = xev.xselectionrequest.selection; responseEvent.xselection.target = xev.xselectionrequest.target; responseEvent.xselection.property = None; //nothing available, by default responseEvent.xselection.time = xev.xselectionrequest.time; //std::cout<<"Request for target:"<<XGetAtomName(x11->dpy(), xev.xselectionrequest.target)<<"\n"; //### presently don't handle XA_STRING as it must be latin1 if (xev.xselectionrequest.target == x11->XA_TARGETS()) { responseEvent.xselection.property = xev.xselectionrequest.property; Atom supported[] = { x11->XA_TEXT(), x11->XA_COMPOUND_TEXT(), x11->UTF8_STRING(), x11->XA_TARGETS() }; XChangeProperty(x11->dpy(), responseEvent.xselection.requestor, xev.xselectionrequest.property, XA_ATOM, 32, PropModeReplace, const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(supported)), 4); } // The encoding of XA_TEXT and XA_COMPOUND_TEXT is not specified // by the ICCCM... So we assume wesnoth native/utf-8 for simplicity. // Modern apps are going to use UTF8_STRING anyway. if (xev.xselectionrequest.target == x11->XA_TEXT() || xev.xselectionrequest.target == x11->XA_COMPOUND_TEXT() || xev.xselectionrequest.target == x11->UTF8_STRING()) { responseEvent.xselection.property = xev.xselectionrequest.property; std::string& selection = (xev.xselectionrequest.selection == XA_PRIMARY) ? primary_string : clipboard_string; XChangeProperty(x11->dpy(), responseEvent.xselection.requestor, xev.xselectionrequest.property, xev.xselectionrequest.target, 8, PropModeReplace, reinterpret_cast<const unsigned char*>(selection.c_str()), selection.length()); } XSendEvent(x11->dpy(), xev.xselectionrequest.requestor, False, NoEventMask, &responseEvent); } } if (xev.type == SelectionClear) { //We no longer own the clipboard, don't try in-process C&P UseX x11; if(xev.xselectionclear.selection == x11->XA_CLIPBOARD()) { clipboard_string.clear(); } else if(xev.xselectionclear.selection == XA_PRIMARY) { primary_string.clear(); } } }
void X11Window::poll() { bool needsResizeUpdate = false; XEvent event, peekEvent; while(XPending(m_display) > 0) { XNextEvent(m_display, &event); // check for repeated key releases bool repatedKeyRelease = false; if(event.type == KeyRelease && XPending(m_display)) { XPeekEvent(m_display, &peekEvent); if((peekEvent.type == KeyPress) && (peekEvent.xkey.keycode == event.xkey.keycode) && ((peekEvent.xkey.time-event.xkey.time) < 2)) repatedKeyRelease = true; } // process keydown and keyrelease events first if(event.type == KeyPress || (event.type == KeyRelease && !repatedKeyRelease)) { // remove caps lock and shift maks XKeyEvent xkey = event.xkey; xkey.state &= ~(ShiftMask | LockMask); // lookup keysym and translate it KeySym keysym; char buf[32]; XLookupString(&xkey, buf, sizeof(buf), &keysym, 0); Fw::Key keyCode = Fw::KeyUnknown; if(m_keyMap.find(keysym) != m_keyMap.end()) keyCode = m_keyMap[keysym]; if(event.type == KeyPress) processKeyDown(keyCode); else if(event.type == KeyRelease) processKeyUp(keyCode); } // call filter because xim will discard KeyPress events when keys still composing if(XFilterEvent(&event, m_window)) continue; // discard repated key releases if(repatedKeyRelease) continue; switch(event.type) { case ClientMessage: { // close event if((Atom)event.xclient.data.l[0] == m_wmDelete && m_onClose) m_onClose(); break; } case ConfigureNotify: { Size newSize(event.xconfigure.width, event.xconfigure.height); Point newPos(event.xconfigure.x, event.xconfigure.y); // updates window size if(m_size != newSize) { m_size = newSize; needsResizeUpdate = true; } // checks if the window is maximized if(m_visible) { m_maximized = false; Atom wmState = XInternAtom(m_display, "_NET_WM_STATE", False); Atom wmStateMaximizedVert = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_VERT", False); Atom wmStateMaximizedHorz = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); Atom actualType; ulong i, numItems, bytesAfter; uchar *propertyValue = NULL; int actualFormat; if(XGetWindowProperty(m_display, m_window, wmState, 0, 1024, False, XA_ATOM, &actualType, &actualFormat, &numItems, &bytesAfter, &propertyValue) == Success) { Atom *atoms = (Atom*)propertyValue; int maximizedMask = 0; for(i=0; i<numItems; ++i) { if(atoms[i] == wmStateMaximizedVert) maximizedMask |= 1; else if(atoms[i] == wmStateMaximizedHorz) maximizedMask |= 2; } if(maximizedMask == 3) m_maximized = true; XFree(propertyValue); } } // updates window pos if(m_visible) m_position = newPos; updateUnmaximizedCoords(); break; } case SelectionRequest: { XEvent respond; XSelectionRequestEvent *req = &(event.xselectionrequest); Atom targets = XInternAtom(m_display, "TARGETS", False); if(req->target == targets) { Atom typeList[] = { XInternAtom(m_display, "UTF8_STRING", False), XInternAtom(m_display, "TEXT", False), XInternAtom(m_display, "STRING", False), XInternAtom(m_display, "text/plain", False), XInternAtom(m_display, "COMPOUND_TEXT", False), XA_STRING }; XChangeProperty(m_display, req->requestor, req->property, req->target, 8, PropModeReplace, (uchar *)&typeList, sizeof(typeList)); respond.xselection.property = req->property; } else { XChangeProperty(m_display, req->requestor, req->property, req->target, 8, PropModeReplace, (uchar *)m_clipboardText.c_str(), m_clipboardText.length()); respond.xselection.property = req->property; } 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; XSendEvent(m_display, req->requestor, 0, 0, &respond); XFlush(m_display); break; } // process text events case KeyPress: { // text cant be insert while holding ctrl or alt if(event.xkey.state & ControlMask || event.xkey.state & Mod1Mask) break; // process key text events KeySym keysym; char buf[32]; memset(buf, 0, 32); int len; // lookup for keyText if(m_xic) { // with xim we can get latin1 input correctly Status status; len = XmbLookupString(m_xic, &event.xkey, buf, sizeof(buf), &keysym, &status); } else { // otherwise use XLookupString, but often it doesn't work right with dead keys static XComposeStatus compose = {NULL, 0}; len = XLookupString(&event.xkey, buf, sizeof(buf), &keysym, &compose); } // filter unwanted characters if(len == 0 || (uchar)(buf[0]) < 32 || keysym == XK_BackSpace || keysym == XK_Return || keysym == XK_Delete || keysym == XK_Escape) break; std::string text = buf; //g_logger.debug("char: ", buf[0], " code: ", (int)((uchar)buf[0])); if(m_onInputEvent && text.length() > 0) { m_inputEvent.reset(Fw::KeyTextInputEvent); m_inputEvent.keyText = text; m_onInputEvent(m_inputEvent); } break; } case ButtonPress: case ButtonRelease: { m_inputEvent.reset(); m_inputEvent.type = (event.type == ButtonPress) ? Fw::MousePressInputEvent : Fw::MouseReleaseInputEvent; switch(event.xbutton.button) { case Button1: m_inputEvent.mouseButton = Fw::MouseLeftButton; m_mouseButtonStates[Fw::MouseLeftButton] = (event.type == ButtonPress); break; case Button3: m_inputEvent.mouseButton = Fw::MouseRightButton; m_mouseButtonStates[Fw::MouseRightButton] = (event.type == ButtonPress); break; case Button2: m_inputEvent.mouseButton = Fw::MouseMidButton; m_mouseButtonStates[Fw::MouseMidButton] = (event.type == ButtonPress); break; case Button4: if(event.type == ButtonPress) { m_inputEvent.type = Fw::MouseWheelInputEvent; m_inputEvent.mouseButton = Fw::MouseMidButton; m_inputEvent.wheelDirection = Fw::MouseWheelUp; } break; case Button5: if(event.type == ButtonPress) { m_inputEvent.type = Fw::MouseWheelInputEvent; m_inputEvent.mouseButton = Fw::MouseMidButton; m_inputEvent.wheelDirection = Fw::MouseWheelDown; } break; default: m_inputEvent.type = Fw::NoInputEvent; break; } if(m_inputEvent.type != Fw::NoInputEvent && m_onInputEvent) m_onInputEvent(m_inputEvent); break; } case MotionNotify: { m_inputEvent.reset(); m_inputEvent.type = Fw::MouseMoveInputEvent; Point newMousePos(event.xbutton.x, event.xbutton.y); m_inputEvent.mouseMoved = newMousePos - m_inputEvent.mousePos; m_inputEvent.mousePos = newMousePos; if(m_onInputEvent) m_onInputEvent(m_inputEvent); break; } case MapNotify: m_visible = true; break; case UnmapNotify: m_visible = false; releaseAllKeys(); break; case FocusIn: m_focused = true; releaseAllKeys(); break; case FocusOut: m_focused = false; releaseAllKeys(); break; case Expose: // window needs redraw break; } } if(needsResizeUpdate && m_onResize) m_onResize(m_size); fireKeysPress(); }
/// // WinCreate() // // This function initialized the native X11 display and window for EGL // EGLBoolean WinCreate(ESContext *esContext, const char *title) { Window root; XSetWindowAttributes swa; XSetWindowAttributes xattr; Atom wm_state; XWMHints hints; XEvent xev; EGLConfig ecfg; EGLint num_config; Window win; /* * X11 native display initialization */ x_display = XOpenDisplay(NULL); if ( x_display == NULL ) { return EGL_FALSE; } root = DefaultRootWindow(x_display); swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask; win = XCreateWindow( x_display, root, 0, 0, esContext->width, esContext->height, 0, CopyFromParent, InputOutput, CopyFromParent, CWEventMask, &swa ); xattr.override_redirect = FALSE; XChangeWindowAttributes ( x_display, win, CWOverrideRedirect, &xattr ); hints.input = TRUE; hints.flags = InputHint; XSetWMHints(x_display, win, &hints); // make the window visible on the screen XMapWindow (x_display, win); XStoreName (x_display, win, title); // get identifiers for the provided atom name strings wm_state = XInternAtom (x_display, "_NET_WM_STATE", FALSE); memset ( &xev, 0, sizeof(xev) ); xev.type = ClientMessage; xev.xclient.window = win; xev.xclient.message_type = wm_state; xev.xclient.format = 32; xev.xclient.data.l[0] = 1; xev.xclient.data.l[1] = FALSE; XSendEvent ( x_display, DefaultRootWindow ( x_display ), FALSE, SubstructureNotifyMask, &xev ); esContext->hWnd = (EGLNativeWindowType) win; return EGL_TRUE; }
/* * Setup X11 wnd System */ void X11_SetupWindow (GF_VideoOutput * vout) { X11VID (); const char *sOpt; xWindow->display = XOpenDisplay (NULL); xWindow->screennum = DefaultScreen (xWindow->display); xWindow->screenptr = DefaultScreenOfDisplay (xWindow->display); xWindow->visual = DefaultVisualOfScreen (xWindow->screenptr); xWindow->depth = DefaultDepth (xWindow->display, xWindow->screennum); switch (xWindow->depth) { case 8: xWindow->pixel_format = GF_PIXEL_GREYSCALE; break; case 16: xWindow->pixel_format = GF_PIXEL_RGB_565; break; case 24: xWindow->pixel_format = GF_PIXEL_RGB_32; break; default: xWindow->pixel_format = GF_PIXEL_GREYSCALE; break; } xWindow->bpp = xWindow->depth / 8; xWindow->bpp = xWindow->bpp == 3 ? 4 : xWindow->bpp; vout->max_screen_width = DisplayWidth(xWindow->display, xWindow->screennum); vout->max_screen_height = DisplayHeight(xWindow->display, xWindow->screennum); /* * Full screen wnd */ xWindow->full_wnd = XCreateWindow (xWindow->display, RootWindowOfScreen (xWindow->screenptr), 0, 0, vout->max_screen_width, vout->max_screen_height, 0, xWindow->depth, InputOutput, xWindow->visual, 0, NULL); XSelectInput(xWindow->display, xWindow->full_wnd, FocusChangeMask | ExposureMask | PointerMotionMask | ButtonReleaseMask | ButtonPressMask | KeyPressMask | KeyReleaseMask); if (!xWindow->par_wnd) { xWindow->w_width = 320; xWindow->w_height = 20; xWindow->wnd = XCreateWindow (xWindow->display, RootWindowOfScreen(xWindow->screenptr), 0, 0, xWindow->w_width, xWindow->w_height, 0, xWindow->depth, InputOutput, xWindow->visual, 0, NULL); XMapWindow (xWindow->display, (Window) xWindow->wnd); } else { XWindowAttributes pwa; XGetWindowAttributes(xWindow->display, xWindow->par_wnd, &pwa); xWindow->w_width = pwa.width; xWindow->w_height = pwa.height; xWindow->wnd = XCreateWindow (xWindow->display, xWindow->par_wnd, pwa.x, pwa.y, xWindow->w_width, xWindow->w_height, 0, xWindow->depth, InputOutput, xWindow->visual, 0, NULL); XMapWindow (xWindow->display, (Window) xWindow->wnd); } XSync(xWindow->display, False); XUnmapWindow (xWindow->display, (Window) xWindow->wnd); XSync(xWindow->display, False); old_handler = XSetErrorHandler(X11_BadAccess_ByPass); selectinput_err = 0; XSelectInput(xWindow->display, xWindow->wnd, FocusChangeMask | StructureNotifyMask | PropertyChangeMask | ExposureMask | PointerMotionMask | ButtonReleaseMask | ButtonPressMask | KeyPressMask | KeyReleaseMask); XSync(xWindow->display, False); XSetErrorHandler(old_handler); if (selectinput_err) { XSelectInput(xWindow->display, xWindow->wnd, StructureNotifyMask | PropertyChangeMask | ExposureMask | KeyPressMask | KeyReleaseMask); GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[X11] Cannot select input focus\n")); } XSync(xWindow->display, False); XMapWindow (xWindow->display, (Window) xWindow->wnd); XSizeHints *Hints = XAllocSizeHints (); Hints->flags = PSize | PMinSize; Hints->min_width = 32; Hints->min_height = 32; Hints->max_height = 4096; Hints->max_width = 4096; if (!xWindow->par_wnd) { XSetWMNormalHints (xWindow->display, xWindow->wnd, Hints); XStoreName (xWindow->display, xWindow->wnd, "GPAC X11 Output"); } Hints->x = 0; Hints->y = 0; Hints->flags |= USPosition; XSetWMNormalHints (xWindow->display, xWindow->full_wnd, Hints); XFree (Hints); xWindow->the_gc = XCreateGC (xWindow->display, xWindow->wnd, 0, NULL); xWindow->videoaccesstype = VIDEO_XI_STANDARD; #ifdef GPAC_HAS_X11_SHM sOpt = gf_modules_get_option((GF_BaseInterface *)vout, "Video", "UseHardwareMemory"); if (sOpt && !strcmp(sOpt, "yes")) { int XShmMajor, XShmMinor; Bool XShmPixmaps; if (XShmQueryVersion(xWindow->display, &XShmMajor, &XShmMinor, &XShmPixmaps)) { /*this is disabled due to flip pb (we cannot reposition backbuffer)*/ if (0 && XShmPixmaps && (XShmPixmapFormat(xWindow->display) == ZPixmap)) { xWindow->videoaccesstype = VIDEO_XI_SHMPIXMAP; } else { xWindow->videoaccesstype = VIDEO_XI_SHMSTD; GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[X11] Using X11 Hardware Blit\n")); } } } #endif GF_SAFEALLOC(xWindow->back_buffer, X11WrapSurface); xWindow->back_buffer->id = -1; XSetWindowAttributes xsw; xsw.border_pixel = WhitePixel (xWindow->display, xWindow->screennum); xsw.background_pixel = BlackPixel (xWindow->display, xWindow->screennum); xsw.win_gravity = NorthWestGravity; XChangeWindowAttributes (xWindow->display, xWindow->wnd, CWBackPixel | CWWinGravity, &xsw); xsw.override_redirect = True; XChangeWindowAttributes(xWindow->display, xWindow->full_wnd, CWOverrideRedirect | CWBackPixel | CWBorderPixel | CWWinGravity, &xsw); if (!xWindow->par_wnd) { xWindow->WM_DELETE_WINDOW = XInternAtom (xWindow->display, "WM_DELETE_WINDOW", False); XSetWMProtocols(xWindow->display, xWindow->wnd, &xWindow->WM_DELETE_WINDOW, 1); } { XEvent ev; long mask; memset (&ev, 0, sizeof (ev)); ev.xclient.type = ClientMessage; ev.xclient.window = RootWindowOfScreen (xWindow->screenptr); ev.xclient.message_type = XInternAtom (xWindow->display, "KWM_KEEP_ON_TOP", False); ev.xclient.format = 32; ev.xclient.data.l[0] = xWindow->full_wnd; ev.xclient.data.l[1] = CurrentTime; mask = SubstructureRedirectMask; XSendEvent (xWindow->display,RootWindowOfScreen (xWindow->screenptr), False, mask, &ev); } #ifdef GPAC_HAS_OPENGL if (xWindow->is_3D_out) { int attribs[64]; int i; i=0; attribs[i++] = GLX_RGBA; attribs[i++] = GLX_RED_SIZE; attribs[i++] = 5; attribs[i++] = GLX_GREEN_SIZE; attribs[i++] = 5; attribs[i++] = GLX_BLUE_SIZE; attribs[i++] = 5; attribs[i++] = GLX_DEPTH_SIZE; attribs[i++] = 16; if (xWindow->gl_cfg.double_buffered) attribs[i++] = GLX_DOUBLEBUFFER; attribs[i++] = None; xWindow->glx_visualinfo = glXChooseVisual(xWindow->display, xWindow->screennum, attribs); if (!xWindow->glx_visualinfo) { GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[X11] Error selecting GL display\n")); } } #endif xWindow->setup_done = 1; }
static inline void post_mouse_motion_event(uiohook_event * const event) { #ifdef USE_XTEST XTestFakeMotionEvent(properties_disp, -1, event->data.mouse.x, event->data.mouse.y, 0); #else XMotionEvent mov_event; mov_event.serial = MotionNotify; mov_event.send_event = False; mov_event.display = properties_disp; mov_event.time = CurrentTime; mov_event.same_screen = True; mov_event.is_hint = NotifyNormal, mov_event.root = DefaultRootWindow(properties_disp); mov_event.window = mov_event.root; mov_event.subwindow = None; mov_event.type = 0x00; mov_event.state = 0x00; mov_event.x_root = 0; mov_event.y_root = 0; mov_event.x = 0; mov_event.y = 0; mov_event.state = convert_to_native_mask(event->mask); mov_event.x = event->data.mouse.x; mov_event.y = event->data.mouse.y; #if defined(USE_XINERAMA) || defined(USE_XRANDR) uint8_t screen_count; screen_data *screens = hook_create_screen_info(&screen_count); if (screen_count > 1) { mov_event.x += screens[0].x; mov_event.y += screens[0].y; } if (screens != NULL) { free(screens); } #endif // These are the same because Window == Root Window. mov_event.x_root = mov_event.x; mov_event.y_root = mov_event.y; long int event_mask = NoEventMask; if (event->type == EVENT_MOUSE_DRAGGED) { #if Button1Mask == Button1MotionMask && \ Button2Mask == Button2MotionMask && \ Button3Mask == Button3MotionMask && \ Button4Mask == Button4MotionMask && \ Button5Mask == Button5MotionMask // This little trick only works if Button#MotionMasks align with // the Button#Masks. event_mask = mov_event.state & (Button1MotionMask | Button2MotionMask | Button2MotionMask | Button3MotionMask | Button5MotionMask); #else // Fallback to some slightly larger... if (event->state & Button1Mask) { event_mask |= Button1MotionMask; } if (event->state & Button2Mask) { event_mask |= Button2MotionMask; } if (event->state & Button3Mask) { event_mask |= Button3MotionMask; } if (event->state & Button4Mask) { event_mask |= Button4MotionMask; } if (event->state & Button5Mask) { event_mask |= Button5MotionMask; } #endif } // NOTE x_mask = NoEventMask. XSendEvent(properties_disp, InputFocus, False, event_mask, (XEvent *) &mov_event); #endif }
int main(int argc, char *argv[]) { // Declare variables char *in = NULL; // piped input char array char inc; // current char of input int inelems = 0; // number of used elements in in int inalloc = 0; // size of in Display *display; // Display connection Window w; // Window XSelectionRequestEvent *req; XEvent ev, re; // X Event Structures int optc; // option char int opti; // option index int dloop = 0; // done loops counter // Stuff that gets set int sloop = 1; char *sdisp = ""; // Flags for command line options static int fverb = 1; // verbose mode (default) static int fhelp = 0; // dispay help static int fvers = 0; // dispay version info // options static struct option long_options[] = { { "quiet" , 0, &fverb, 0 }, { "help" , 0, &fhelp, 1 }, { "version" , 0, &fvers, 1 }, { "display" , 1, 0, 0 }, { "loops" , 1, 0, 0 } }; while (1){ // Get the option into optc optc = getopt_long_only( argc, argv, "abc", long_options, &opti ); // Escape the loop if there are no more options if (optc == -1) break; if (optarg){ // the if below segfaults if optarg is null. Why??? if ( long_options[opti].flag == 0 ) { // display option if ( strncmp(long_options[opti].name, "display") == 0) { sdisp = optarg; printf("Display: %s\n", optarg); } // loops option if ( strncmp(long_options[opti].name, "loops" ) == 0) { sloop = atoi(optarg); printf("Loops: %s\n", optarg); } } } } if (fhelp){ printf("Usage: xclip [OPTIONS]\n"); printf("Puts data from standard input into a X server selection for pasting.\n"); printf("\n"); printf("-l, --loops number of selection requests to wait for before exiting\n"); printf("-d, --display X display to connect to (eg \"localhost:0\"\n"); printf("-v, --verbose verbose mode (default)\n"); printf("-q, --quiet terse mode (for use in scripts, etc)\n"); printf("-h, --help usage information\n"); printf("\n"); printf("Report bugs to <*****@*****.**>\n"); exit(EXIT_SUCCESS); } if (fvers){ printf("xclip version %1.2f\n", VERSION); printf("Copyright (C) 2001 Kim Saunders\n"); printf("Distributed under the terms of the GNU GPL\n"); exit(EXIT_SUCCESS); } while (optind < argc){ printf("Arg: %s\n", argv[optind++]); } if ( display = XOpenDisplay(sdisp) ) // Display connection { printf("Connected to X server.\n"); } else { printf("Could not connect to X server.\n"); perror(NULL); exit(EXIT_FAILURE); } // Put chars into inc from stdin until we hit EOF while ( (inc = getchar()) != EOF){ // If in is full (used elems = allocated elems) if (inelems == inalloc){ // Allocate another 10 elems inalloc += 10; in = (char *)realloc((char *)in, inalloc * sizeof(char)); if(in == NULL){ printf("Error: Could not allocate memory\n"); exit(EXIT_FAILURE); } } in[inelems] = inc; inelems++; } // Create a window to own that will trap events w = XCreateSimpleWindow( display, DefaultRootWindow(display), 0, 0, 1, 1, 0, 0, 0 ); // Take control of the selection XSetSelectionOwner(display, XA_PRIMARY, w, CurrentTime); if (sloop == 1){ printf("Waiting for one selection request.\n"); } if (sloop < 1){ printf("Waiting for selection requests, Control-C to quit\n"); } if (sloop > 1){ printf("Waiting for %i selection requests, Control-C to quit\n", sloop); } while (dloop < sloop || sloop < 1){ if (sloop > 1){ printf(" Waiting for selection request %i ", dloop + 1); printf("of %i.\n" , sloop); } if (sloop == 1){ printf(" Waiting for a selection request.\n"); } if (sloop < 1){ printf(" Waiting for selection request number %i\n", dloop + 1); } XNextEvent(display, &ev); // Get the next event while (ev.type != SelectionRequest && ev.type != SelectionClear ){ XNextEvent(display, &ev); } if (ev.type == SelectionRequest){ // printf(" Selection has been pasted.\n"); req = &(ev.xselectionrequest); XChangeProperty( display, req->requestor, req->property, XA_STRING, 8, PropModeReplace, (unsigned char*) in, inelems ); re.xselection.property = req->property; re.xselection.type = SelectionNotify; re.xselection.display = req->display; re.xselection.requestor = req->requestor; re.xselection.selection = req->selection; re.xselection.target = req->target; re.xselection.time = req->time; XSendEvent(display, req->requestor, 0, 0, &re); XFlush(display); } if (ev.type == SelectionClear){ // Another app is telling us that it now owns the selection, // so we don't get selectionrequest events from the x server // any more, time to exit... printf("Error: Another application took ownership of the selection.\n"); exit(EXIT_FAILURE); } dloop++; } // Disconnect from the X server XCloseDisplay(display); // Exit return(EXIT_SUCCESS); }
static gboolean na_tray_manager_manage_screen_x11 (NaTrayManager *manager, GdkScreen *screen) { GdkDisplay *display; Screen *xscreen; GtkWidget *invisible; char *selection_atom_name; guint32 timestamp; g_return_val_if_fail (NA_IS_TRAY_MANAGER (manager), FALSE); g_return_val_if_fail (manager->screen == NULL, FALSE); /* If there's already a manager running on the screen * we can't create another one. */ #if 0 if (na_tray_manager_check_running_screen_x11 (screen)) return FALSE; #endif manager->screen = screen; display = gdk_screen_get_display (screen); xscreen = GDK_SCREEN_XSCREEN (screen); invisible = gtk_invisible_new_for_screen (screen); gtk_widget_realize (invisible); gtk_widget_add_events (invisible, GDK_PROPERTY_CHANGE_MASK | GDK_STRUCTURE_MASK); selection_atom_name = g_strdup_printf ("_NET_SYSTEM_TRAY_S%d", gdk_screen_get_number (screen)); manager->selection_atom = gdk_atom_intern (selection_atom_name, FALSE); g_free (selection_atom_name); manager->invisible = invisible; g_object_ref (G_OBJECT (manager->invisible)); na_tray_manager_set_orientation_property (manager); na_tray_manager_set_visual_property (manager); na_tray_manager_set_padding_property (manager); timestamp = gdk_x11_get_server_time (gtk_widget_get_window(invisible)); /* Check if we could set the selection owner successfully */ if (gdk_selection_owner_set_for_display (display, gtk_widget_get_window(invisible), manager->selection_atom, timestamp, TRUE)) { XClientMessageEvent xev; GdkAtom opcode_atom; GdkAtom message_data_atom; xev.type = ClientMessage; xev.window = RootWindowOfScreen (xscreen); xev.message_type = gdk_x11_get_xatom_by_name_for_display (display, "MANAGER"); xev.format = 32; xev.data.l[0] = timestamp; xev.data.l[1] = gdk_x11_atom_to_xatom_for_display (display, manager->selection_atom); xev.data.l[2] = GDK_WINDOW_XWINDOW (gtk_widget_get_window(invisible)); xev.data.l[3] = 0; /* manager specific data */ xev.data.l[4] = 0; /* manager specific data */ XSendEvent (GDK_DISPLAY_XDISPLAY (display), RootWindowOfScreen (xscreen), False, StructureNotifyMask, (XEvent *)&xev); opcode_atom = gdk_atom_intern ("_NET_SYSTEM_TRAY_OPCODE", FALSE); manager->opcode_atom = gdk_x11_atom_to_xatom_for_display (display, opcode_atom); message_data_atom = gdk_atom_intern ("_NET_SYSTEM_TRAY_MESSAGE_DATA", FALSE); /* Add a window filter */ #if 0 /* This is for when we lose the selection of _NET_SYSTEM_TRAY_Sx */ g_signal_connect (invisible, "selection-clear-event", G_CALLBACK (na_tray_manager_selection_clear_event), manager); #endif /* This is for SYSTEM_TRAY_REQUEST_DOCK and SelectionClear */ gdk_window_add_filter (gtk_widget_get_window(invisible), na_tray_manager_window_filter, manager); /* This is for SYSTEM_TRAY_BEGIN_MESSAGE and SYSTEM_TRAY_CANCEL_MESSAGE */ gdk_display_add_client_message_filter (display, opcode_atom, na_tray_manager_handle_client_message_opcode, manager); /* This is for _NET_SYSTEM_TRAY_MESSAGE_DATA */ gdk_display_add_client_message_filter (display, message_data_atom, na_tray_manager_handle_client_message_message_data, manager); return TRUE; } else { gtk_widget_destroy (invisible); g_object_unref (invisible); manager->invisible = NULL; manager->screen = NULL; return FALSE; } }
void QX11Data::motifdndHandle(QWidget *widget, const XEvent * xe, bool /* passive */) { XEvent event = *xe; XClientMessageEvent cm ; DndData dnd_data ; char receiver ; if (!(DndParseClientMessage ((XClientMessageEvent*)&event, &dnd_data, &receiver))) { return; } switch (dnd_data.reason) { case DND_DRAG_MOTION: { QPoint p = widget->mapFromGlobal(QPoint(dnd_data.x, dnd_data.y)); QWidget *c = widget->childAt(p); if (!c || !c->acceptDrops()) { // not over a drop site if (dropWidget) { QDragLeaveEvent dragLeaveEvent; QApplication::sendEvent(dropWidget, &dragLeaveEvent); dropWidget = 0; lastAcceptedAction = Qt::IgnoreAction; dnd_data.reason = DND_DROP_SITE_LEAVE; dnd_data.time = X11->time; DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, receiver); XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm) ; } else { dnd_data.reason = DND_DRAG_MOTION; dnd_data.status = DND_NO_DROP_SITE; dnd_data.time = X11->time; dnd_data.operation = DND_NOOP; dnd_data.operations = DND_NOOP; DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, receiver); XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm) ; } } else { Q_ASSERT(c != 0); p = c->mapFrom(widget, p); if (dropWidget != c) { if (dropWidget) { QDragLeaveEvent le; QApplication::sendEvent(dropWidget, &le); } dropWidget = c; lastAcceptedAction = Qt::IgnoreAction; const Qt::DropActions possibleActions = DndOperationsToQtDropActions(dnd_data.operations); QDragEnterEvent de(p, possibleActions, QDragManager::self()->dropData, QApplication::mouseButtons(), QApplication::keyboardModifiers()); QApplication::sendEvent(dropWidget, &de); dnd_data.reason = DND_DROP_SITE_ENTER; dnd_data.time = X11->time; if (de.isAccepted()) { lastAcceptedAction = de.dropAction(); dnd_data.status = DND_VALID_DROP_SITE; dnd_data.operation = QtDropActionToDndOperation(lastAcceptedAction); } else { dnd_data.status = DND_INVALID_DROP_SITE; dnd_data.operation = DND_NOOP; dnd_data.operations = DND_NOOP; } DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, receiver); XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm); } else { const Qt::DropActions possibleActions = DndOperationsToQtDropActions(dnd_data.operations); QDragMoveEvent me(p, possibleActions, QDragManager::self()->dropData, QApplication::mouseButtons(), QApplication::keyboardModifiers()); if (lastAcceptedAction != Qt::IgnoreAction) { me.setDropAction(lastAcceptedAction); me.accept(); } QApplication::sendEvent(dropWidget, &me); dnd_data.reason = DND_DRAG_MOTION; dnd_data.time = X11->time; if (me.isAccepted()) { lastAcceptedAction = me.dropAction(); dnd_data.status = DND_VALID_DROP_SITE; dnd_data.operation = QtDropActionToDndOperation(lastAcceptedAction); } else { dnd_data.status = DND_INVALID_DROP_SITE; dnd_data.operation = DND_NOOP; dnd_data.operations = DND_NOOP; } DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, receiver); XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm); } } break; } case DND_TOP_LEVEL_ENTER: { /* get the size of our drop site for later use */ motifdnd_active = true; sourceWindow = dnd_data.src_window; /* no answer needed, just read source property */ DndReadSourceProperty (event.xclient.display, sourceWindow, dnd_data.property, &src_targets, &num_src_targets); break; } case DND_TOP_LEVEL_LEAVE: { XEvent nextEvent; if (XCheckTypedWindowEvent(X11->display, widget->winId(), ClientMessage, &nextEvent)) { // we just want to check, not eat (should use XPeekIfEvent) XPutBackEvent(X11->display, &nextEvent); if (DndParseClientMessage (&nextEvent.xclient, &dnd_data, &receiver) && dnd_data.reason == DND_DROP_START) { // expecting drop next, keeping DnD alive break; } } // not expecting drop, need to send drag leave events and such here if (dropWidget) { QDragLeaveEvent le; QApplication::sendEvent(dropWidget, &le); } sourceWindow = XNone; dropWidget = 0; lastAcceptedAction = Qt::IgnoreAction; motifdnd_active = false; break; } case DND_OPERATION_CHANGED: // ### need to echo break; case DND_DROP_START: { Q_ASSERT(motifdnd_active); Q_ASSERT(sourceWindow == dnd_data.src_window); if (!dropWidget || lastAcceptedAction == Qt::IgnoreAction) { // echo DROP_START dnd_data.reason = DND_DROP_START; dnd_data.status = DND_NO_DROP_SITE; dnd_data.operation = DND_NOOP; dnd_data.operations = DND_NOOP; DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, 0); XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm); // we have to convert selection in order to indicate failure to the initiator XConvertSelection (X11->display, dnd_data.property, ATOM(XmTRANSFER_FAILURE), dnd_data.property, dnd_data.src_window, dnd_data.time); if (dropWidget) { QDragLeaveEvent e; QApplication::sendEvent(dropWidget, &e); } motifdnd_active = false; sourceWindow = XNone; dropWidget = 0; lastAcceptedAction = Qt::IgnoreAction; return; } // store selection and its time Dnd_selection = dnd_data.property; Dnd_selection_time = dnd_data.time; QPoint p(dnd_data.x, dnd_data.y); QDropEvent de(dropWidget->mapFromGlobal(p), Qt::CopyAction, QDragManager::self()->dropData, QApplication::mouseButtons(), QApplication::keyboardModifiers()); if (lastAcceptedAction != Qt::IgnoreAction) { de.setDropAction(lastAcceptedAction); de.accept(); } QApplication::sendEvent(dropWidget, &de); // reset Dnd_selection = XNone; Dnd_selection_time = 0; // echo DROP_START depending on the result of the dropEvent if (de.isAccepted()) { dnd_data.reason = DND_DROP_START; dnd_data.status = DND_VALID_DROP_SITE; dnd_data.operation = QtDropActionToDndOperation(de.dropAction()); } else { dnd_data.reason = DND_DROP_START; dnd_data.status = DND_NO_DROP_SITE; dnd_data.operation = DND_NOOP; dnd_data.operations = DND_NOOP; } DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, 0); XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm); sourceWindow = XNone; dropWidget = 0; lastAcceptedAction = Qt::IgnoreAction; motifdnd_active = false; break; } default: break; } // end of switch (dnd_data.reason) }