Example #1
0
static void
weston_wm_send_selection_notify(struct weston_wm *wm, xcb_atom_t property)
{
	xcb_selection_notify_event_t selection_notify;

	memset(&selection_notify, 0, sizeof selection_notify);
	selection_notify.response_type = XCB_SELECTION_NOTIFY;
	selection_notify.sequence = 0;
	selection_notify.time = wm->selection_request.time;
	selection_notify.requestor = wm->selection_request.requestor;
	selection_notify.selection = wm->selection_request.selection;
	selection_notify.target = wm->selection_request.target;
	selection_notify.property = property;

	xcb_send_event(wm->conn, 0, /* propagate */
		       wm->selection_request.requestor,
		       XCB_EVENT_MASK_NO_EVENT, (char *) &selection_notify);
}
Example #2
0
void
send_client_message(xcb_window_t destination, xcb_window_t window,
		    xcb_atom_t message, const uint32_t data[])
{
    xcb_client_message_event_t event;

    event.response_type = XCB_CLIENT_MESSAGE;
    event.format = 32;
    event.sequence = 0;
    event.window = window;
    event.type = message;

    int i;
    for (i = 0; i < 5; i++) {
	event.data.data32[i] = data[i];
    }

    xcb_send_event(conn, 0, destination, mask, (const char *) &event);

}
Example #3
0
// === MinimizeWindow() ===
void LXCB::MinimizeWindow(WId win){ //request that the window be unmapped/minimized
  if(DEBUG){ qDebug() << "XCB: MinimizeWindow()"; }
  if(win==0){ return; }
  //Note: Fluxbox completely removes this window from the open list if unmapped manually
 // xcb_unmap_window(QX11Info::connection(), win);
  //xcb_flush(QX11Info::connection()); //make sure the command is sent out right away
	
  //Need to send a client message event for the window so the WM picks it up
  xcb_client_message_event_t event;
    event.response_type = XCB_CLIENT_MESSAGE;
    event.format = 32;
    event.window = win;
    event.type = EWMH._NET_WM_STATE;
    event.data.data32[0] = 1; //set to toggle (switch back and forth)
    event.data.data32[1] = EWMH._NET_WM_STATE_HIDDEN;
    event.data.data32[2] = 0;
    event.data.data32[3] = 0;
    event.data.data32[4] = 0;

  xcb_send_event(QX11Info::connection(), 0, QX11Info::appRootWindow(),  XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event);
}
Example #4
0
// === SetAsSticky() ===
void LXCB::SetAsSticky(WId win){
  if(DEBUG){ qDebug() << "XCB: SetAsSticky()"; }
  if(win==0){ return; }
  //Need to send a client message event for the window so the WM picks it up
  xcb_client_message_event_t event;
    event.response_type = XCB_CLIENT_MESSAGE;
    event.format = 32;
    event.window = win;
    event.type = EWMH._NET_WM_STATE;
    event.data.data32[0] = 1; //set to enabled
    event.data.data32[1] = EWMH._NET_WM_STATE_STICKY;
    event.data.data32[2] = 0;
    event.data.data32[3] = 0;
    event.data.data32[4] = 0;

  xcb_send_event(QX11Info::connection(), 0, QX11Info::appRootWindow(),  XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event);
	
  //This method changes the property on the window directly - the WM is not aware of it	
  /*xcb_change_property( QX11Info::connection(), XCB_PROP_MODE_APPEND, win, EWMH._NET_WM_STATE, XCB_ATOM_ATOM, 32, 1, &(EWMH._NET_WM_STATE_STICKY) );
  xcb_flush(QX11Info::connection()); //apply it right away*/
}
Example #5
0
File: window.c Project: feler/ceres
/* window_configure  {{{
 * @window the window be changed
 * @new_geom the new geometry
 * @border border in pixels
 */
void
window_configure(xcb_window_t window, uint16_t x, uint16_t y,
        uint16_t width, uint16_t height, int border)
{
    xcb_configure_notify_event_t conf;

    /* Fill the struct */
    conf.event = window;
    conf.window = window;
    conf.response_type = XCB_CONFIGURE_NOTIFY;
    conf.above_sibling = XCB_NONE;
    conf.override_redirect = false;
    conf.x = x;
    conf.y = y;
    conf.width = width;
    conf.height = width;

    /* Update */
    xcb_send_event(rootconf.connection, false,
            window, XCB_EVENT_MASK_STRUCTURE_NOTIFY,
            (const char *) &conf);
} /*  }}} */
Example #6
0
void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *event)
{
    if (event->format == 32 && event->type == atom(QXcbAtom::WM_PROTOCOLS)) {
        if (event->data.data32[0] == atom(QXcbAtom::WM_DELETE_WINDOW)) {
            QWindowSystemInterface::handleCloseEvent(widget());
        } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_PING)) {
            xcb_client_message_event_t reply = *event;

            reply.response_type = XCB_CLIENT_MESSAGE;
            reply.window = m_screen->root();

            xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&reply);
            xcb_flush(xcb_connection());
        } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_SYNC_REQUEST)) {
            if (!m_hasReceivedSyncRequest) {
                m_hasReceivedSyncRequest = true;
                printf("Window manager supports _NET_WM_SYNC_REQUEST, syncing resizes\n");
            }
            m_syncValue.lo = event->data.data32[2];
            m_syncValue.hi = event->data.data32[3];
        }
    }
}
Example #7
0
void QXcbScreen::sendStartupMessage(const QByteArray &message) const
{
    xcb_window_t rootWindow = root();

    xcb_client_message_event_t ev;
    ev.response_type = XCB_CLIENT_MESSAGE;
    ev.format = 8;
    ev.type = connection()->atom(QXcbAtom::_NET_STARTUP_INFO_BEGIN);
    ev.window = rootWindow;
    int sent = 0;
    int length = message.length() + 1; // include NUL byte
    const char *data = message.constData();
    do {
        if (sent == 20)
            ev.type = connection()->atom(QXcbAtom::_NET_STARTUP_INFO);

        const int start = sent;
        const int numBytes = qMin(length - start, 20);
        memcpy(ev.data.data8, data + start, numBytes);
        xcb_send_event(connection()->xcb_connection(), false, rootWindow, XCB_EVENT_MASK_PROPERTY_CHANGE, (const char *) &ev);

        sent += numBytes;
    } while (sent < length);
}
Example #8
0
// ===== startSystemTray() =====
WId LXCB::startSystemTray(int screen){
  qDebug() << "Starting System Tray:" << screen;
  //Setup the freedesktop standards compliance
  
  //Get the appropriate atom for this screen
  QString str = QString("_NET_SYSTEM_TRAY_S%1").arg(QString::number(screen));
  //qDebug() << "Default Screen Atom Name:" << str;
  xcb_intern_atom_reply_t *treply = xcb_intern_atom_reply(QX11Info::connection(), \
			xcb_intern_atom(QX11Info::connection(), 0, str.length(), str.toLocal8Bit()), NULL);
  xcb_intern_atom_reply_t *oreply = xcb_intern_atom_reply(QX11Info::connection(), \
			xcb_intern_atom(QX11Info::connection(), 0, 28, "_NET_SYSTEM_TRAY_ORIENTATION"), NULL);  
  xcb_intern_atom_reply_t *vreply = xcb_intern_atom_reply(QX11Info::connection(), \
			xcb_intern_atom(QX11Info::connection(), 0, 23, "_NET_SYSTEM_TRAY_VISUAL"), NULL);  
  if(treply==0){
    qDebug() << " - ERROR: Could not initialize _NET_SYSTEM_TRAY_S<num> atom";
    return 0;
  }
  if(oreply==0){
    qDebug() << " - ERROR: Could not initialize _NET_SYSTEM_TRAY_ORIENTATION atom";
    return 0;	  
  }
  if(vreply==0){
    qDebug() << " - ERROR: Could not initialize _NET_SYSTEM_TRAY_VISUAL atom";
    return 0;	  
  }
  xcb_atom_t _NET_SYSTEM_TRAY_S = treply->atom;
  xcb_atom_t _NET_SYSTEM_TRAY_ORIENTATION = oreply->atom;
  xcb_atom_t _NET_SYSTEM_TRAY_VISUAL = vreply->atom;
  free(treply); //done with atom generation
  free(oreply);
  free(vreply);
  
  //Make sure that there is no other system tray running
  xcb_get_selection_owner_reply_t *ownreply = xcb_get_selection_owner_reply(QX11Info::connection(), \
						xcb_get_selection_owner_unchecked(QX11Info::connection(), _NET_SYSTEM_TRAY_S), NULL);
  if(ownreply==0){
    qWarning() << " - Could not get owner selection reply";
    return 0;
  }
  if(ownreply->owner != 0){
    free(ownreply);
    qWarning() << " - An alternate system tray is currently in use";
    return 0;
  }
  free(ownreply);
  
  //Create a simple window to register as the tray (not visible - just off the screen)
  xcb_screen_t *root_screen = xcb_aux_get_screen(QX11Info::connection(), QX11Info::appScreen());
  uint32_t params[] = {1};
  WId LuminaSessionTrayID = xcb_generate_id(QX11Info::connection()); //need a new ID
    xcb_create_window(QX11Info::connection(), root_screen->root_depth, \
		LuminaSessionTrayID, root_screen->root, -1, -1, 1, 1, 0, \
		XCB_WINDOW_CLASS_INPUT_OUTPUT, root_screen->root_visual, \
		XCB_CW_OVERRIDE_REDIRECT, params);
		
  //Now register this widget as the system tray
  xcb_set_selection_owner(QX11Info::connection(), LuminaSessionTrayID, _NET_SYSTEM_TRAY_S, XCB_CURRENT_TIME);
  //Make sure that it was registered properly
  ownreply = xcb_get_selection_owner_reply(QX11Info::connection(), \
						xcb_get_selection_owner_unchecked(QX11Info::connection(), _NET_SYSTEM_TRAY_S), NULL);
  
  if(ownreply==0 || ownreply->owner != LuminaSessionTrayID){
    if(ownreply!=0){ free(ownreply); }
    qWarning() << " - Could not register the system tray";
    xcb_destroy_window(QX11Info::connection(), LuminaSessionTrayID);
    return 0;
  }
  free(ownreply); //done with structure
  
  //Now register the orientation of the system tray
  uint32_t orient = _NET_SYSTEM_TRAY_ORIENTATION_HORZ;
   xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, LuminaSessionTrayID, \
			_NET_SYSTEM_TRAY_ORIENTATION, XCB_ATOM_CARDINAL, 32, 1, &orient);

  //Now set the visual ID for the system tray (same as the root window, but TrueColor)
    xcb_visualtype_t *type = xcb_aux_find_visual_by_attrs(root_screen, XCB_VISUAL_CLASS_TRUE_COLOR, 32);
    if(type!=0){
      xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, LuminaSessionTrayID, \
	  _NET_SYSTEM_TRAY_VISUAL, XCB_ATOM_VISUALID, 32, 1, &type->visual_id);	    
    }else{
      qWarning() << " - Could not set TrueColor visual for system tray";
    }
  
  //Finally, send out an X event letting others know that the system tray is up and running
   xcb_client_message_event_t event;
    event.response_type = XCB_CLIENT_MESSAGE;
    event.format = 32;
    event.window = root_screen->root;
    event.type = EWMH.MANAGER; //MANAGER atom
    event.data.data32[0] = XCB_TIME_CURRENT_TIME; //CurrentTime;  
    event.data.data32[1] = _NET_SYSTEM_TRAY_S; //_NET_SYSTEM_TRAY_S atom
    event.data.data32[2] = LuminaSessionTrayID;
    event.data.data32[3] = 0;
    event.data.data32[4] = 0;

    xcb_send_event(QX11Info::connection(), 0, root_screen->root,  XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event);
  
  //Success
  return LuminaSessionTrayID;
}
Example #9
0
/** Changes the EWMH state of the window */
static void set_wm_state (vout_window_t *wnd, bool on, xcb_atom_t state)
{
    vout_window_sys_t *sys = wnd->sys;
    /* From EWMH "_WM_STATE" */
    xcb_client_message_event_t ev = {
         .response_type = XCB_CLIENT_MESSAGE,
         .format = 32,
         .window = wnd->handle.xid,
         .type = sys->wm_state,
    };

    ev.data.data32[0] = on ? NET_WM_STATE_ADD : NET_WM_STATE_REMOVE;
    ev.data.data32[1] = state;
    ev.data.data32[2] = 0;
    ev.data.data32[3] = 1;

    /* From ICCCM "Changing Window State" */
    xcb_send_event (sys->conn, 0, sys->root,
                    XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
                    XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
                    (const char *)&ev);
}


static int Control (vout_window_t *wnd, int cmd, va_list ap)
{
    vout_window_sys_t *p_sys = wnd->sys;
    xcb_connection_t *conn = p_sys->conn;

    switch (cmd)
    {
        case VOUT_WINDOW_SET_SIZE:
        {
            if (p_sys->embedded)
                return VLC_EGENERIC;

            unsigned width = va_arg (ap, unsigned);
            unsigned height = va_arg (ap, unsigned);
            const uint32_t values[] = { width, height, };

            xcb_configure_window (conn, wnd->handle.xid,
                                  XCB_CONFIG_WINDOW_WIDTH |
                                  XCB_CONFIG_WINDOW_HEIGHT, values);
            break;
        }

        case VOUT_WINDOW_SET_STATE:
        {
            unsigned state = va_arg (ap, unsigned);
            bool above = (state & VOUT_WINDOW_STATE_ABOVE) != 0;
            bool below = (state & VOUT_WINDOW_STATE_BELOW) != 0;

            set_wm_state (wnd, above, p_sys->wm_state_above);
            set_wm_state (wnd, below, p_sys->wm_state_below);
            break;
        }

        case VOUT_WINDOW_SET_FULLSCREEN:
        {
            bool fs = va_arg (ap, int);
            if (!fs && var_GetBool (wnd, "video-wallpaper"))
                return VLC_EGENERIC;
            set_wm_state (wnd, fs, p_sys->wm_state_fullscreen);
            break;
        }

        default:
            msg_Err (wnd, "request %d not implemented", cmd);
            return VLC_EGENERIC;
    }
    xcb_flush (p_sys->conn);
    return VLC_SUCCESS;
}
Example #10
0
void configure_request(xcb_generic_event_t *evt)
{
	xcb_configure_request_event_t *e = (xcb_configure_request_event_t *) evt;

	PRINTF("configure request %X\n", e->window);

	coordinates_t loc;
	bool is_managed = locate_window(e->window, &loc);
	client_t *c = (is_managed ? loc.node->client : NULL);
	int w = 0, h = 0;

	if (is_managed && !is_floating(c)) {
		if (e->value_mask & XCB_CONFIG_WINDOW_X)
			c->floating_rectangle.x = e->x;
		if (e->value_mask & XCB_CONFIG_WINDOW_Y)
			c->floating_rectangle.y = e->y;
		if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH)
			w = e->width;
		if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT)
			h = e->height;

		if (w != 0) {
			restrain_floating_width(c, &w);
			c->floating_rectangle.width = w;
		}

		if (h != 0) {
			restrain_floating_height(c, &h);
			c->floating_rectangle.height = h;
		}

		xcb_configure_notify_event_t evt;
		xcb_rectangle_t rect;
		xcb_window_t win = c->window;
		unsigned int bw = c->border_width;

		if (c->fullscreen)
			rect = loc.monitor->rectangle;
		else
			rect = c->tiled_rectangle;

		evt.response_type = XCB_CONFIGURE_NOTIFY;
		evt.event = win;
		evt.window = win;
		evt.above_sibling = XCB_NONE;
		evt.x = rect.x;
		evt.y = rect.y;
		evt.width = rect.width;
		evt.height = rect.height;
		evt.border_width = bw;
		evt.override_redirect = false;

		xcb_send_event(dpy, false, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (const char *) &evt);

		if (c->pseudo_tiled)
			arrange(loc.monitor, loc.desktop);
	} else {
		uint16_t mask = 0;
		uint32_t values[7];
		unsigned short i = 0;

		if (e->value_mask & XCB_CONFIG_WINDOW_X) {
			mask |= XCB_CONFIG_WINDOW_X;
			values[i++] = e->x;
			if (is_managed)
				c->floating_rectangle.x = e->x;
		}

		if (e->value_mask & XCB_CONFIG_WINDOW_Y) {
			mask |= XCB_CONFIG_WINDOW_Y;
			values[i++] = e->y;
			if (is_managed)
				c->floating_rectangle.y = e->y;
		}

		if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) {
			mask |= XCB_CONFIG_WINDOW_WIDTH;
			w = e->width;
			if (is_managed) {
				restrain_floating_width(c, &w);
				c->floating_rectangle.width = w;
			}
			values[i++] = w;
		}

		if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) {
			mask |= XCB_CONFIG_WINDOW_HEIGHT;
			h = e->height;
			if (is_managed) {
				restrain_floating_height(c, &h);
				c->floating_rectangle.height = h;
			}
			values[i++] = h;
		}

		if (!is_managed && e->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH) {
			mask |= XCB_CONFIG_WINDOW_BORDER_WIDTH;
			values[i++] = e->border_width;
		}

		if (e->value_mask & XCB_CONFIG_WINDOW_SIBLING) {
			mask |= XCB_CONFIG_WINDOW_SIBLING;
			values[i++] = e->sibling;
		}

		if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) {
			mask |= XCB_CONFIG_WINDOW_STACK_MODE;
			values[i++] = e->stack_mode;
		}

		xcb_configure_window(dpy, e->window, mask, values);
	}

	if (is_managed)
		translate_client(monitor_from_client(c), loc.monitor, c);
}
Example #11
0
void QXcbDrag::move(const QMouseEvent *me)
{
    // The mouse event is in the coordinate system of the window that started the drag.
    // We do not know which window that was at this point, so we just use the device pixel ratio
    // of the QGuiApplication. This will break once we support screens with different DPR. Fixing
    // this properly requires some redesign of the drag and drop architecture.
    static const int dpr = int(qApp->devicePixelRatio());
    QBasicDrag::move(me);
    QPoint globalPos = me->globalPos();

    if (source_sameanswer.contains(globalPos) && source_sameanswer.isValid())
        return;

    const QList<QXcbScreen *> &screens = connection()->screens();
    QXcbScreen *screen = connection()->primaryScreen();
    for (int i = 0; i < screens.size(); ++i) {
        if (screens.at(i)->geometry().contains(globalPos)) {
            screen = screens.at(i);
            break;
        }
    }
    if (screen != current_screen) {
        // ### need to recreate the shaped pixmap window?
//    int screen = QCursor::x11Screen();
//    if ((qt_xdnd_current_screen == -1 && screen != X11->defaultScreen) || (screen != qt_xdnd_current_screen)) {
//        // recreate the pixmap on the new screen...
//        delete xdnd_data.deco;
//        QWidget* parent = object->source()->window()->x11Info().screen() == screen
//            ? object->source()->window() : QApplication::desktop()->screen(screen);
//        xdnd_data.deco = new QShapedPixmapWidget(parent);
//        if (!QWidget::mouseGrabber()) {
//            updatePixmap();
//            xdnd_data.deco->grabMouse();
//        }
//    }
//    xdnd_data.deco->move(QCursor::pos() - xdnd_data.deco->pm_hot);
        current_screen = screen;
    }


//    qt_xdnd_current_screen = screen;
    xcb_window_t rootwin = current_screen->root();
    xcb_translate_coordinates_reply_t *translate =
            ::translateCoordinates(connection(), rootwin, rootwin, globalPos.x() * dpr, globalPos.y() * dpr);
    if (!translate)
        return;

    xcb_window_t target = translate->child;
    int lx = translate->dst_x;
    int ly = translate->dst_y;
    free (translate);

    if (target && target != rootwin) {
        xcb_window_t src = rootwin;
        while (target != 0) {
            DNDDEBUG << "checking target for XdndAware" << target << lx << ly;

            // translate coordinates
            translate = ::translateCoordinates(connection(), src, target, lx, ly);
            if (!translate) {
                target = 0;
                break;
            }
            lx = translate->dst_x;
            ly = translate->dst_y;
            src = target;
            xcb_window_t child = translate->child;
            free(translate);

            // check if it has XdndAware
            xcb_get_property_cookie_t cookie = Q_XCB_CALL(xcb_get_property(xcb_connection(), false, target,
                                                          atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0));
            xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0);
            bool aware = reply && reply->type != XCB_NONE;
            free(reply);
            if (aware) {
                DNDDEBUG << "Found XdndAware on " << target;
                break;
            }

            target = child;
        }

        if (!target || target == shapedPixmapWindow()->handle()->winId()) {
            DNDDEBUG << "need to find real window";
            target = findRealWindow(globalPos, rootwin, 6, true);
            if (target == 0)
                target = findRealWindow(globalPos, rootwin, 6, false);
            DNDDEBUG << "real window found" << target;
        }
    }

    QXcbWindow *w = 0;
    if (target) {
        w = connection()->platformWindowFromId(target);
        if (w && (w->window()->type() == Qt::Desktop) /*&& !w->acceptDrops()*/)
            w = 0;
    } else {
        w = 0;
        target = rootwin;
    }

    xcb_window_t proxy_target = xdndProxy(connection(), target);
    if (!proxy_target)
        proxy_target = target;
    int target_version = 1;

    if (proxy_target) {
        xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, proxy_target,
                                                            atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 1);
        xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0);
        if (!reply || reply->type == XCB_NONE)
            target = 0;

        target_version = *(uint32_t *)xcb_get_property_value(reply);
        target_version = qMin(xdnd_version, target_version ? target_version : 1);

        free(reply);
    }

    if (target != current_target) {
        if (current_target)
            send_leave();

        current_target = target;
        current_proxy_target = proxy_target;
        if (target) {
            int flags = target_version << 24;
            if (drag_types.size() > 3)
                flags |= 0x0001;

            xcb_client_message_event_t enter;
            enter.response_type = XCB_CLIENT_MESSAGE;
            enter.window = target;
            enter.format = 32;
            enter.type = atom(QXcbAtom::XdndEnter);
            enter.data.data32[0] = connection()->clipboard()->owner();
            enter.data.data32[1] = flags;
            enter.data.data32[2] = drag_types.size()>0 ? drag_types.at(0) : 0;
            enter.data.data32[3] = drag_types.size()>1 ? drag_types.at(1) : 0;
            enter.data.data32[4] = drag_types.size()>2 ? drag_types.at(2) : 0;
            // provisionally set the rectangle to 5x5 pixels...
            source_sameanswer = QRect(globalPos.x() - 2, globalPos.y() -2 , 5, 5);

            DEBUG() << "sending Xdnd enter source=" << enter.data.data32[0];
            if (w)
                handleEnter(w->window(), &enter);
            else if (target)
                xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&enter);
            waiting_for_status = false;
        }
    }

    if (waiting_for_status)
        return;

    if (target) {
        waiting_for_status = true;

        xcb_client_message_event_t move;
        move.response_type = XCB_CLIENT_MESSAGE;
        move.window = target;
        move.format = 32;
        move.type = atom(QXcbAtom::XdndPosition);
        move.data.data32[0] = connection()->clipboard()->owner();
        move.data.data32[1] = 0; // flags
        move.data.data32[2] = (globalPos.x() * dpr << 16) + globalPos.y() * dpr;
        move.data.data32[3] = connection()->time();
        move.data.data32[4] = toXdndAction(defaultAction(currentDrag()->supportedActions(), QGuiApplication::keyboardModifiers()));
        DEBUG() << "sending Xdnd position source=" << move.data.data32[0] << "target=" << move.window;

        source_time = connection()->time();

        if (w)
            handle_xdnd_position(w->window(), &move);
        else
            xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&move);
    }
}
Example #12
0
    //_____________________________________________
    void SizeGrip::sendMoveResizeEvent( QPoint position )
    {

        #if OXYGEN_HAVE_X11
        if( !QX11Info::isPlatformX11() ) return;

        // pointer to connection
        auto connection( QX11Info::connection() );

        // client
        auto c = m_decoration.data()->client().data();

        /*
        get root position matching position
        need to use xcb because the embedding of the widget
        breaks QT's mapToGlobal and other methods
        */
        QPoint rootPosition( position );
        xcb_get_geometry_cookie_t cookie( xcb_get_geometry( connection, winId() ) );
        ScopedPointer<xcb_get_geometry_reply_t> reply( xcb_get_geometry_reply( connection, cookie, 0x0 ) );
        if( reply )
        {

            // translate coordinates
            xcb_translate_coordinates_cookie_t coordCookie( xcb_translate_coordinates(
                connection, winId(), reply.data()->root,
                -reply.data()->border_width,
                -reply.data()->border_width ) );

            ScopedPointer< xcb_translate_coordinates_reply_t> coordReply( xcb_translate_coordinates_reply( connection, coordCookie, 0x0 ) );

            if( coordReply )
            {
                rootPosition.rx() += coordReply.data()->dst_x;
                rootPosition.ry() += coordReply.data()->dst_y;
            }

        }

        // move/resize atom
        if( !m_moveResizeAtom )
        {

            // create atom if not found
            const QString atomName( "_NET_WM_MOVERESIZE" );
            xcb_intern_atom_cookie_t cookie( xcb_intern_atom( connection, false, atomName.size(), qPrintable( atomName ) ) );
            ScopedPointer<xcb_intern_atom_reply_t> reply( xcb_intern_atom_reply( connection, cookie, 0x0 ) );
            m_moveResizeAtom = reply ? reply->atom:0;

        }

        if( !m_moveResizeAtom ) return;

        // button release event
        xcb_button_release_event_t releaseEvent;
        memset(&releaseEvent, 0, sizeof(releaseEvent));

        releaseEvent.response_type = XCB_BUTTON_RELEASE;
        releaseEvent.event =  winId();
        releaseEvent.child = XCB_WINDOW_NONE;
        releaseEvent.root = QX11Info::appRootWindow();
        releaseEvent.event_x = position.x();
        releaseEvent.event_y = position.y();
        releaseEvent.root_x = rootPosition.x();
        releaseEvent.root_y = rootPosition.y();
        releaseEvent.detail = XCB_BUTTON_INDEX_1;
        releaseEvent.state = XCB_BUTTON_MASK_1;
        releaseEvent.time = XCB_CURRENT_TIME;
        releaseEvent.same_screen = true;
        xcb_send_event( connection, false, winId(), XCB_EVENT_MASK_BUTTON_RELEASE, reinterpret_cast<const char*>(&releaseEvent));

        xcb_ungrab_pointer( connection, XCB_TIME_CURRENT_TIME );

        // move resize event
        xcb_client_message_event_t clientMessageEvent;
        memset(&clientMessageEvent, 0, sizeof(clientMessageEvent));

        clientMessageEvent.response_type = XCB_CLIENT_MESSAGE;
        clientMessageEvent.type = m_moveResizeAtom;
        clientMessageEvent.format = 32;
        clientMessageEvent.window = c->windowId();
        clientMessageEvent.data.data32[0] = rootPosition.x();
        clientMessageEvent.data.data32[1] = rootPosition.y();
        clientMessageEvent.data.data32[2] = 4; // bottom right
        clientMessageEvent.data.data32[3] = Qt::LeftButton;
        clientMessageEvent.data.data32[4] = 0;

        xcb_send_event( connection, false, QX11Info::appRootWindow(),
            XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
            XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
            reinterpret_cast<const char*>(&clientMessageEvent) );

        xcb_flush( connection );
        #endif

    }
Example #13
0
static void forwardMouseEventToRoot(QMouseEvent* event) {
    xcb_ungrab_pointer(QX11Info::connection(), event->timestamp());
    // forward the event to the root window
    xcb_button_press_event_t xcb_event;
    uint32_t mask = 0;
    xcb_event.state = 0;
    switch(event->type()) {
    case QEvent::MouseButtonPress:
        xcb_event.response_type = XCB_BUTTON_PRESS;
        mask = XCB_EVENT_MASK_BUTTON_PRESS;
        break;
    case QEvent::MouseButtonRelease:
        xcb_event.response_type = XCB_BUTTON_RELEASE;
        mask = XCB_EVENT_MASK_BUTTON_RELEASE;
        break;
    default:
        return;
    }

    // convert Qt button to XCB button
    switch(event->button()) {
    case Qt::LeftButton:
        xcb_event.detail = 1;
        xcb_event.state |= XCB_BUTTON_MASK_1;
        break;
    case Qt::MiddleButton:
        xcb_event.detail = 2;
        xcb_event.state |= XCB_BUTTON_MASK_2;
        break;
    case Qt::RightButton:
        xcb_event.detail = 3;
        xcb_event.state |= XCB_BUTTON_MASK_3;
        break;
    default:
        xcb_event.detail = 0;
    }

    // convert Qt modifiers to XCB states
    if(event->modifiers() & Qt::ShiftModifier) {
        xcb_event.state |= XCB_MOD_MASK_SHIFT;
    }
    if(event->modifiers() & Qt::ControlModifier) {
        xcb_event.state |= XCB_MOD_MASK_SHIFT;
    }
    if(event->modifiers() & Qt::AltModifier) {
        xcb_event.state |= XCB_MOD_MASK_1;
    }

    xcb_event.sequence = 0;
    xcb_event.time = event->timestamp();

    WId root = QX11Info::appRootWindow(QX11Info::appScreen());
    xcb_event.event = root;
    xcb_event.root = root;
    xcb_event.child = 0;

    xcb_event.root_x = event->globalX();
    xcb_event.root_y = event->globalY();
    xcb_event.event_x = event->x();
    xcb_event.event_y = event->y();
    xcb_event.same_screen = 1;

    xcb_send_event(QX11Info::connection(), 0, root, mask, (char*)&xcb_event);
    xcb_flush(QX11Info::connection());
}
Example #14
0
void SNIProxy::sendClick(uint8_t mouseButton, int x, int y)
{
    //it's best not to look at this code
    //GTK doesn't like send_events and double checks the mouse position matches where the window is and is top level
    //in order to solve this we move the embed container over to where the mouse is then replay the event using send_event
    //if patching, test with xchat + xchat context menus

    //note x,y are not actually where the mouse is, but the plasmoid
    //ideally we should make this match the plasmoid hit area

    qCDebug(SNIPROXY) << "Sending click " << mouseButton << "to" << x << y;

    auto c = QX11Info::connection();

    //set our window so the middle is where the mouse is
    const uint32_t stackAboveData[] = {XCB_STACK_MODE_ABOVE};
    xcb_configure_window(c, m_containerWid, XCB_CONFIG_WINDOW_STACK_MODE, stackAboveData);

    const uint32_t config_vals[4] = {x, y, s_embedSize, s_embedSize };
    xcb_configure_window(c, m_containerWid,
                             XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
                             config_vals);
    //mouse down
    {
        xcb_button_press_event_t* event = new xcb_button_press_event_t;
        memset(event, 0x00, sizeof(xcb_button_press_event_t));
        event->response_type = XCB_BUTTON_PRESS;
        event->event = m_windowId;
        event->time = QX11Info::getTimestamp();
        event->same_screen = 1;
        event->root = QX11Info::appRootWindow();
        event->root_x = x;
        event->root_y = y;
        event->event_x = 0;
        event->event_y = 0;
        event->child = 0;
        event->state = 0;
        event->detail = mouseButton;

        xcb_send_event(c, false, m_windowId, XCB_EVENT_MASK_BUTTON_PRESS, (char *) event);
        free(event);
    }

    //mouse up
    {
        xcb_button_release_event_t* event = new xcb_button_release_event_t;
        memset(event, 0x00, sizeof(xcb_button_release_event_t));
        event->response_type = XCB_BUTTON_RELEASE;
        event->event = m_windowId;
        event->time = QX11Info::getTimestamp();
        event->same_screen = 1;
        event->root = QX11Info::appRootWindow();
        event->root_x = x;
        event->root_y = y;
        event->event_x = 0;
        event->event_y = 0;
        event->child = 0;
        event->state = 0;
        event->detail = mouseButton;

        xcb_send_event(c, false, m_windowId, XCB_EVENT_MASK_BUTTON_RELEASE, (char *) event);
        free(event);
    }
#ifndef VISUAL_DEBUG
    const uint32_t stackBelowData[] = {XCB_STACK_MODE_BELOW};
    xcb_configure_window(c, m_containerWid, XCB_CONFIG_WINDOW_STACK_MODE, stackBelowData);
#endif
    }
Example #15
0
void configure_request(xcb_generic_event_t *evt)
{
	xcb_configure_request_event_t *e = (xcb_configure_request_event_t *) evt;

	coordinates_t loc;
	bool is_managed = locate_window(e->window, &loc);
	client_t *c = (is_managed ? loc.node->client : NULL);
	int w = 0, h = 0;

	if (is_managed && !IS_FLOATING(c)) {
		if (e->value_mask & XCB_CONFIG_WINDOW_X) {
			c->floating_rectangle.x = e->x;
		}
		if (e->value_mask & XCB_CONFIG_WINDOW_Y) {
			c->floating_rectangle.y = e->y;
		}
		if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) {
			w = e->width;
		}
		if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) {
			h = e->height;
		}

		if (w != 0) {
			restrain_floating_width(c, &w);
			c->floating_rectangle.width = w;
		}

		if (h != 0) {
			restrain_floating_height(c, &h);
			c->floating_rectangle.height = h;
		}

		xcb_configure_notify_event_t evt;
		unsigned int bw = c->border_width;

		xcb_rectangle_t rect = get_rectangle(loc.desktop, loc.node);

		evt.response_type = XCB_CONFIGURE_NOTIFY;
		evt.event = e->window;
		evt.window = e->window;
		evt.above_sibling = XCB_NONE;
		evt.x = rect.x;
		evt.y = rect.y;
		evt.width = rect.width;
		evt.height = rect.height;
		evt.border_width = bw;
		evt.override_redirect = false;

		xcb_send_event(dpy, false, e->window, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (const char *) &evt);

		if (c->state == STATE_PSEUDO_TILED) {
			arrange(loc.monitor, loc.desktop);
		}
	} else {
		uint16_t mask = 0;
		uint32_t values[7];
		unsigned short i = 0;

		if (e->value_mask & XCB_CONFIG_WINDOW_X) {
			mask |= XCB_CONFIG_WINDOW_X;
			values[i++] = e->x;
			if (is_managed) {
				c->floating_rectangle.x = e->x;
			}
		}

		if (e->value_mask & XCB_CONFIG_WINDOW_Y) {
			mask |= XCB_CONFIG_WINDOW_Y;
			values[i++] = e->y;
			if (is_managed) {
				c->floating_rectangle.y = e->y;
			}
		}

		if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) {
			mask |= XCB_CONFIG_WINDOW_WIDTH;
			w = e->width;
			if (is_managed) {
				restrain_floating_width(c, &w);
				c->floating_rectangle.width = w;
			}
			values[i++] = w;
		}

		if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) {
			mask |= XCB_CONFIG_WINDOW_HEIGHT;
			h = e->height;
			if (is_managed) {
				restrain_floating_height(c, &h);
				c->floating_rectangle.height = h;
			}
			values[i++] = h;
		}

		if (!is_managed && e->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH) {
			mask |= XCB_CONFIG_WINDOW_BORDER_WIDTH;
			values[i++] = e->border_width;
		}

		if (!is_managed && e->value_mask & XCB_CONFIG_WINDOW_SIBLING) {
			mask |= XCB_CONFIG_WINDOW_SIBLING;
			values[i++] = e->sibling;
		}

		if (!is_managed && e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) {
			mask |= XCB_CONFIG_WINDOW_STACK_MODE;
			values[i++] = e->stack_mode;
		}

		xcb_configure_window(dpy, e->window, mask, values);

		if (is_managed && mask & XCB_CONFIG_WINDOW_X_Y_WIDTH_HEIGHT) {
			xcb_rectangle_t r = c->floating_rectangle;
			put_status(SBSC_MASK_NODE_GEOMETRY, "node_geometry 0x%X 0x%X 0x%X %ux%u+%i+%i\n", loc.monitor->id, loc.desktop->id, e->window, r.width, r.height, r.x, r.y);
		}
	}

	if (is_managed) {
		monitor_t *m = monitor_from_client(c);
		adapt_geometry(&m->rectangle, &loc.monitor->rectangle, loc.node);
	}
}