Ejemplo n.º 1
1
/*
   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
}
Ejemplo n.º 2
0
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
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
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__


}
Ejemplo n.º 5
0
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);
	}
}
Ejemplo n.º 6
0
	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);
	}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
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");
	}
Ejemplo n.º 9
0
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
}
Ejemplo n.º 11
0
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();
}
Ejemplo n.º 12
0
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));
}
Ejemplo n.º 13
0
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; 
}
Ejemplo n.º 14
0
// 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; 
}
Ejemplo n.º 15
0
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;
}
Ejemplo n.º 16
0
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;
}
Ejemplo n.º 17
0
/* 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);
				}
			}
		}
	}
Ejemplo n.º 18
0
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 );
}
Ejemplo n.º 19
0
	// 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;
		}

	}
Ejemplo n.º 20
0
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
}
Ejemplo n.º 22
0
/**
 * 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;
}
Ejemplo n.º 23
0
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();
		}
	}
}
Ejemplo n.º 24
0
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();
}
Ejemplo n.º 25
0
///
//  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;
}
Ejemplo n.º 26
0
/*
 * 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;
}
Ejemplo n.º 27
0
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
}
Ejemplo n.º 28
0
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;
    }
}
Ejemplo n.º 30
0
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)
}