Beispiel #1
0
void map_client(client_t *c)
{
    XWindowAttributes attr;
    strut_t s = { 0, 0, 0, 0 };
    XWMHints *hints;
    int btn, want_raise = 1;

    XGrabServer(dpy);

    XGetWindowAttributes(dpy, c->win, &attr);
    collect_struts(c, &s);

    if (attr.map_state == IsViewable) {
        c->ignore_unmap++;
        reparent(c, &s);
        if (get_wm_state(c->win) == IconicState) {
            c->ignore_unmap++;
            XUnmapWindow(dpy, c->win);
        } else {
            set_wm_state(c, NormalState);
            do_map(c, want_raise);
        }
    } else {
        if ((hints = XGetWMHints(dpy, c->win))) {
            if (hints->flags & StateHint)
                set_wm_state(c, hints->initial_state);
            XFree(hints);
        } else {
            set_wm_state(c, NormalState);
        }
        if (!init_geom(c, &s) && opt_imap) {
            btn = sweep(c, map_curs, recalc_map, SWEEP_DOWN, &s);
            if (btn == Button2)
                btn = sweep(c, resize_curs, recalc_resize, SWEEP_UP, &s);
            if (btn == Button3)
                want_raise = 0;
        }
#ifdef DEBUG
        dump_geom(c, "set to");
        dump_info(c);
#endif
        reparent(c, &s);
        if (get_wm_state(c->win) == NormalState)
            do_map(c, want_raise);
    }

    XSync(dpy, False);
    c->name = get_wm_name(c->win); // horrible kludge
    XUngrabServer(dpy);
}
Beispiel #2
0
void remove_client(Client *c) {
  Client *p;

  LOG_DEBUG("remove_client() : Removing...\n");

  if (!c || !c->xstuff) return;

  XGrabServer(dpy);
  ignore_xerror = 1;

  /* ICCCM 4.1.3.1
   * "When the window is withdrawn, the window manager will either
   *  change the state field's value to WithdrawnState or it will
   *  remove the WM_STATE property entirely."
   * EWMH 1.3
   * "The Window Manager should remove the property whenever a
   *  window is withdrawn but it should leave the property in
   *  place when it is shutting down." (both _NET_WM_DESKTOP and
   *  _NET_WM_STATE) */

  if (c->remove) {
    LOG_DEBUG("\tremove_client() : setting WithdrawnState\n");
    set_wm_state(c, WithdrawnState);
    XDeleteProperty(dpy, c->xstuff->window, xa_net_wm_desktop);
    XDeleteProperty(dpy, c->xstuff->window, xa_net_wm_state);
  }

  ungravitate(c);
  if (c->xstuff->screen)
      XReparentWindow(dpy, c->xstuff->window, c->xstuff->screen->root, c->x, c->y);
  XSetWindowBorderWidth(dpy, c->xstuff->window, c->old_border);
  XRemoveFromSaveSet(dpy, c->xstuff->window);
  if (c->xstuff->parent)
    XDestroyWindow(dpy, c->xstuff->parent);

  if (head_client == c) head_client = c->next;
  else for (p = head_client; p && p->next; p = p->next)
    if (p->next == c) p->next = c->next;

  if (current == c)
    current = NULL;  /* an enter event should set this up again */

  free(c->xstuff);
  free(c);
#ifdef DEBUG
  {
    Client *pp;
    int i = 0;
    for (pp = head_client; pp; pp = pp->next)
      i++;
    LOG_DEBUG("\tremove_client() : free(), window count now %d\n", i);
  }
#endif

  XUngrabServer(dpy);
  XFlush(dpy);
  ignore_xerror = 0;
  LOG_DEBUG("remove_client() returning\n");
}
Beispiel #3
0
void del_client(client_t *c, int mode)
{
    client_t *p;

    XGrabServer(dpy);
    XSetErrorHandler(ignore_xerror);

#ifdef DEBUG
    dump_name(c, "removing", 'r');
    dump_removal(c, mode);
#endif

    if (mode == DEL_WITHDRAW) {
        set_wm_state(c, WithdrawnState);
    } else /* mode == DEL_REMAP */ {
        if (c->zoomed) {
            c->geom.x = c->save.x;
            c->geom.y = c->save.y;
            c->geom.w = c->save.w;
            c->geom.h = c->save.h;
            XResizeWindow(dpy, c->win, c->geom.w, c->geom.h);
        }
        XMapWindow(dpy, c->win);
    }

    remove_atom(root, net_client_list, XA_WINDOW, c->win);
    remove_atom(root, net_client_stack, XA_WINDOW, c->win);

    XSetWindowBorderWidth(dpy, c->win, c->old_bw);
#ifdef XFT
    if (c->xftdraw)
        XftDrawDestroy(c->xftdraw);
#endif

    XReparentWindow(dpy, c->win, root, c->geom.x, c->geom.y);
    XRemoveFromSaveSet(dpy, c->win);
    XDestroyWindow(dpy, c->frame);

    if (head == c)
        head = c->next;
    else for (p = head; p && p->next; p = p->next)
        if (p->next == c)
            p->next = c->next;

    if (c->name) XFree(c->name);
    free(c);

    XSync(dpy, False);
    XSetErrorHandler(handle_xerror);
    XUngrabServer(dpy);
}
Beispiel #4
0
void remove_client(Client *c, int from_cleanup)
{
	Client *p = NULL;

	XGrabServer(dpy);
	XSetErrorHandler(ignore_xerror);

	if (c->name && c->name != null_str)
		XFree(c->name);

	if (from_cleanup)
		unhide(c, NO_RAISE);
	else if (!from_cleanup)
		set_wm_state(c, WithdrawnState);

	ungravitate(c);
	XReparentWindow(dpy, c->window, root, c->x, c->y);
	XRemoveFromSaveSet(dpy, c->window);
	XSetWindowBorderWidth(dpy, c->window, 1);

	XDestroyWindow(dpy, c->parent);

	if (head_client == c)
		head_client = c->next;
	else {
		for (p = head_client; p && p->next; p = p->next)
			if (p->next == c) p->next = c->next;
	}

	if (c->size)
		XFree(c->size);

	/* an enter event should set this up again */
	if (c == current) {
		current = NULL;
		if (prev_focused[c->vdesk] == c)
			prev_focused[c->vdesk] = NULL;
	}

	free(c);

	XSync(dpy, False);
	XSetErrorHandler(handle_xerror);
	XUngrabServer(dpy);
}
Beispiel #5
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;
}
Beispiel #6
0
void make_new_client(Window w)
{
	Client *c, *p;
	XWindowAttributes attr;
	long dummy;
	XWMHints *hints;
	XSizeHints* shints;

	XGrabServer(dpy);
	XSetErrorHandler(ignore_xerror);
	hints = XGetWMHints(dpy, w);

	shints = XAllocSizeHints();
	XGetWMNormalHints(dpy, w, shints, &dummy);

	c = (Client *)calloc(1, sizeof(Client));
	c->next = head_client;
	head_client = c;

	c->window = w;
	c->name = null_str;

	/* try these here instead */
	c->size = shints;

	XClassHint* hint = XAllocClassHint();
	XGetClassHint(dpy, w, hint);
	if (hint->res_class) {
		c->name = hint->res_class;
		if (hint->res_name)
			XFree(hint->res_name);
	}
	XFree(hint);

	XGetWindowAttributes(dpy, c->window, &attr);

	c->x = attr.x;
	c->y = attr.y;
	c->width = attr.width;
	c->height = attr.height;
	c->border = opt_bw;
	c->oldw = c->oldh = 0;
	c->vdesk = vdesk;
	c->index = 0;

	if (!(attr.map_state == IsViewable)) {
		init_position(c);
		if (hints && hints->flags & StateHint)
			set_wm_state(c, hints->initial_state);
	}

	if (hints)
		XFree(hints);

	/* client is initialised */

	gravitate(c);
	reparent(c);

	XGrabButton(dpy, AnyButton, Mod1Mask, c->parent, False,
		    ButtonMask, GrabModeSync, GrabModeAsync, None, None);
	XGrabButton(dpy, AnyButton, 0, c->parent, False,
		    ButtonPressMask, GrabModeSync, GrabModeAsync, None, None);
	XMapWindow(dpy, c->window);
	XMapRaised(dpy, c->parent);
	set_wm_state(c, NormalState);

	XSync(dpy, False);
	XSetErrorHandler(handle_xerror);
	XUngrabServer(dpy);

	throwUnmaps = 0;

again:
	for (p = c->next; p; p = p->next) {
		if (c->index == p->index && !strcmp(c->name, p->name)) {
			c->index++;
			goto again;
		}
	}
}
Beispiel #7
0
void handle_event(XEvent *ev) {
	client *c = owner(ev->xany.window);
	#ifdef DEBUG_EVENTS
	if(ev->type != Expose && ev->type != MotionNotify && !(ev->type == ConfigureNotify && ev->xconfigure.window != root)) /* this makes the output slightly more manageable */
		printf(NAME ": handle_event(): got %s\n\twindow: 0x%X (%s)\n", event_name(ev), (unsigned int) ev->xany.window, c ? c->name : ((ev->xany.window == root) ? "root" : "unknown"));
	#endif
	if((evh && evh(ev)) || button_handle_event(ev) || ewmh_handle_event(ev) || screens_handle_event(ev)) {
		#ifdef DEBUG_EVENTS
		if(ev->type != Expose && ev->type != MotionNotify && (ev->type != ConfigureNotify && ev->xconfigure.window != root))
			printf(NAME ": handle_event(): external event handler claimed last event\n");
		#endif
		return;
	}
	if(c) {
		if(!has_child(c->parent, c->window) && ev->type != DestroyNotify && ev->type != UnmapNotify)
			return;
		switch(ev->type) {
			case UnmapNotify:
				if(c->window == ev->xunmap.window) {
					#ifdef DEBUG_EVENTS
					printf(NAME ": handle_event(): handling UnmapNotify event\n\twindow: 0x%X (%s)\n", (unsigned int) c->window, c->name);
					#endif
					if(has_child(c->parent, c->window)) {
						client_deparent(c);
						set_wm_state(c->window, WithdrawnState);
					}
					client_remove(c);
					ewmh_update_clist();
				}
				return;
			case PropertyNotify:
				if(ev->xproperty.atom == XA_WM_NAME) {
					#ifdef DEBUG_EVENTS
					printf(NAME ": handle_event(): handling PropertyNotify event\n\twindow: 0x%X (%s)\n\tproperty: XA_WM_NAME\n", (unsigned int) c->window, c->name);
					#endif
					if(c->name != no_title)
						XFree(c->name);
					#ifdef USE_XFT
					if(xftfont)
						XftDrawDestroy(c->title_draw);
					#endif
					XFreePixmap(dpy, c->title_pixmap);
					XFetchName(dpy, c->window, &c->name);
					client_update_name(c);
					XClearWindow(dpy, c->title);
					if(evh == wlist_handle_event) {
						XClearWindow(dpy, c->wlist_item);
						wlist_item_draw(c);
					}
				}
				if(ev->xproperty.atom == XA_WM_NORMAL_HINTS) {
					#ifdef DEBUG_EVENTS
					printf(NAME ": handle_event(): handling PropertyNotify event\n\twindow: 0x%X (%s)\n\tproperty: XA_WM_NORMAL_HINTS\n", (unsigned int) c->window, c->name);
					#endif
					get_normal_hints(c);
				}
				return;
			case ClientMessage:
				if(ev->xclient.message_type == xa_wm_change_state && ev->xclient.data.l[0] == IconicState) {
					#ifdef DEBUG_EVENTS
					printf(NAME ": handling ClientMessage event\n\twindow: 0x%X (%s)\n", (unsigned int) c->window, c->name);
					#endif
					client_iconify(c);
					return;
				}
				break; /* we might later need this event */
			case EnterNotify:
				if(c != current && !(c->flags & CLICK_FOCUS) && !click_focus && ev->xcrossing.mode != NotifyGrab && ev->xcrossing.mode != NotifyUngrab && ev->xcrossing.detail != NotifyInferior && (ev->xcrossing.window == c->parent || ev->xcrossing.window == c->wlist_item) && ev->xcrossing.send_event == False) {
					#ifdef DEBUG_EVENTS
					printf(NAME ": handle_event(): handling EnterNotify event\n\twindow: 0x%X (%s)\n", (unsigned int) c->window, c->name);
					#endif
					client_focus(c, true);
				}
				return;
			case Expose:
				if(ev->xexpose.count == 0 && evh == wlist_handle_event && c && ev->xexpose.window == c->wlist_item)
					wlist_item_draw(c);
				return;
			case ButtonPress:
				#ifdef DEBUG_EVENTS
				printf(NAME ": handle_event(): handling ButtonPress event\n\twindow: 0x%X (%s)\n", (unsigned int) c->window, c->name);
				#endif
				if(c != current)
					client_focus(c, true);
				XAllowEvents(dpy, ReplayPointer, CurrentTime);
				if(ev->xbutton.window != c->window) {
					if(lastclick + doubleclick_time > ev->xbutton.time && lastbutton == ev->xbutton.button && lastclick_client == c) {
						client_action(c, buttonaction(ev->xbutton.button, true), ev);
						lastclick = 0;
						lastclick_client = NULL;
						lastbutton = None;
						return;
					}
					lastclick = ev->xbutton.time;
					lastclick_client = c;
					lastbutton = ev->xbutton.button;
					client_action(c, buttonaction(ev->xbutton.button, false), ev);
				} else if(click_raise)
					client_raise(c);
				return;
			case FocusIn: /* we ignore pointer events, these happen if the input focus is on the root window */
				if(allow_focus_stealing && c != current && ev->xfocus.mode != NotifyGrab && ev->xfocus.mode != NotifyUngrab && ev->xfocus.detail != NotifyPointer) {
					#ifdef DEBUG_EVENTS
					printf(NAME ": handle_event(): handling FocusIn event\n\twindow: 0x%X (%s)\n", (unsigned int) c->window, c->name);
					#endif
					client_focus(c, false);
				}
				return;
			case FocusOut:
				if(c == current && ev->xfocus.mode != NotifyGrab && ev->xfocus.mode != NotifyUngrab && ev->xfocus.detail != NotifyInferior) {
					#ifdef DEBUG_EVENTS
					printf(NAME ": handle_event(): handling FocusOut event\n\twindow: 0x%X (%s)\n", (unsigned int) c->window, c->name);
					#endif
					if(allow_focus_stealing && ev->xfocus.detail != NotifyAncestor) {
						#ifdef DEBUG_EVENTS
						printf("\tfocus lost\n");
						#endif
						client_focus(NULL, false); /* we do this so windows that aren't managed can take focus */
					} else {
						#ifdef DEBUG_EVENTS
						printf("\tre-focussing this window\n");
						#endif
						take_focus(c);
					}
				}
				return;
			#ifdef USE_SHAPE
			default:
				if(ev->type == shape_event) {
					#ifdef DEBUG_EVENTS
					printf(NAME ": handle_event(): handling ShapeNotify event\n\twindow 0x%X (%s)\n", (unsigned int) c->window, c->name);
					#endif
					set_shape(c);
					return;
				}
			#endif
		}
	}
	switch(ev->type) {
		case MapRequest:
			c = owner(ev->xmaprequest.window);
			#ifdef DEBUG_EVENTS
			printf(NAME ": handle_event(): handling MapRequest event\n\twindow: 0x%X (%s)\n", (unsigned int) ev->xmaprequest.window, c ? c->name : "unknown");
			#endif
			if(c) {
				if(c->flags & ICONIC && has_child(c->parent, c->window)) {
					client_restore(c);
					if(focus_new)
						client_focus(c, true);
				}
			} else if(has_child(root, ev->xmaprequest.window))
				client_add(ev->xmaprequest.window, false);
			return;
		case DestroyNotify:
			c = owner(ev->xdestroywindow.window);
			if(c)
				if(c->window == ev->xdestroywindow.window) {
					#ifdef DEBUG_EVENTS
					printf(NAME ": handle_event(): handling DestroyNotify event\n\twindow 0x%X (%s)\n", (unsigned int) c->window, c->name);
					#endif
					client_remove(c);
				}
			return;
		case ConfigureRequest:
			c = owner(ev->xconfigurerequest.window);
			#ifdef DEBUG_EVENTS
			printf(NAME ": handle_event(): handling ConfigureRequest event\n\twindow 0x%X (%s)\n", (unsigned int) ev->xconfigurerequest.window, c ? c->name : "unknown");
			#endif
			if(correct_center)
				screens_correct_center(&ev->xconfigurerequest.x, &ev->xconfigurerequest.y, &ev->xconfigurerequest.width, &ev->xconfigurerequest.height);
			if(c) {
				if(!has_child(c->parent, c->window))
					return;
				if(ev->xconfigurerequest.value_mask & CWX)
					c->x = ev->xconfigurerequest.x - gxo(c, false);
				if(ev->xconfigurerequest.value_mask & CWY)
					c->y = ev->xconfigurerequest.y - gyo(c, false);
				if(ev->xconfigurerequest.value_mask & CWWidth)
					c->width = ev->xconfigurerequest.width;
				if(ev->xconfigurerequest.value_mask & CWHeight)
					c->height = ev->xconfigurerequest.height;
				client_update(c);
				#ifdef DEBUG
				printf(NAME ": handle_event(): reconfigured client 0x%X (%s) to %ix%i+%i+%i\n", (unsigned int) c->window, c->name, c->width, c->height, c->x, c->y);
				#endif
			} else if(has_child(root, ev->xconfigurerequest.window)) {
				XWindowChanges wc;
				wc.sibling = ev->xconfigurerequest.above;
				wc.stack_mode = ev->xconfigurerequest.detail;
				wc.x = ev->xconfigurerequest.x;
				wc.y = ev->xconfigurerequest.y;
				wc.width = ev->xconfigurerequest.width;
				wc.height = ev->xconfigurerequest.height;
				XConfigureWindow(dpy, ev->xconfigurerequest.window, ev->xconfigurerequest.value_mask, &wc);
			}
			return;
		case MapNotify:
			if(correct_center_unmanaged && ev->xany.window == root && !owner(ev->xmap.window)) {
				#ifdef DEBUG_EVENTS
				printf(NAME ": handle_event(): handling MapNotify event\n\twindow 0x%X (unknown)\n", (unsigned int) ev->xmap.window);
				#endif
				window_correct_center(ev->xmap.window);
			}
			return;
		case MappingNotify:
			if(ev->xmapping.request != MappingPointer) {
				#ifdef DEBUG_EVENTS
				printf(NAME ": handle_event(): handling MappingNotify event\n");
				#endif
				keys_ungrab();
				XRefreshKeyboardMapping(&ev->xmapping);
				keys_update();
			}
			return;
		case KeyPress:
			#ifdef DEBUG_EVENTS
			printf(NAME ": handle_event(): handling KeyPress event\n");
			#endif
			client_action(current, keyaction(ev), ev);
			return;
		case ButtonPress:
			if(ev->xbutton.window != root)
				return;
			#ifdef DEBUG_EVENTS
			printf(NAME ": handle_event(): handling ButtonPress event\n");
			#endif
			if(lastclick + doubleclick_time > ev->xbutton.time && lastbutton == ev->xbutton.button && lastclick_client == NULL) {
				client_action(current, root_buttonaction(ev->xbutton.button, true), ev);
				lastclick = 0;
				lastclick_client = NULL;
				lastbutton = None;
				return;
			}
			lastclick = ev->xbutton.time;
			lastclick_client = NULL;
			lastbutton = ev->xbutton.button;
			client_action(current, root_buttonaction(ev->xbutton.button, false), ev);
			return;
		case ClientMessage:
			if(ev->xclient.message_type == xa_internal_message) {
				if(((Atom) ev->xclient.data.l[0]) == xa_quit) {
					#ifdef DEBUG
					printf(NAME ": handle_event(): quit message received\n");
					#endif
					exit(0);
				}
				if(((Atom) ev->xclient.data.l[0]) == xa_reinit) {
					#ifdef DEBUG
					printf(NAME ": handle_event(): reinitialize message received\n");
					#endif
					cfg_reinitialize();
				}
			}
	}
}