/** Toggle the selected client to free * \param cmd uicb_t type unused */ void uicb_togglefree(uicb_t cmd) { (void)cmd; if(!sel || sel->screen != screen_get_sel() || (sel->flags & FSSFlag)) return; sel->flags ^= FreeFlag; if((sel->flags & FreeFlag)) { sel->flags &= ~(TileFlag | MaxFlag | LMaxFlag); client_moveresize(sel, sel->free_geo, True); client_raise(sel); } else { sel->free_geo = sel->geo; sel->ogeo = sel->geo; } client_update_attributes(sel); tags[selscreen][seltag[selscreen]].layout.func(selscreen); return; }
void mousefunc_client_resize(void *ctx, union arg *arg, enum xev xev) { struct client_ctx *cc = ctx; XEvent ev; Time ltime = 0; struct screen_ctx *sc = cc->sc; if (cc->flags & CLIENT_FREEZE) return; client_raise(cc); client_ptrsave(cc); xu_ptr_setpos(cc->win, cc->geom.w, cc->geom.h); if (XGrabPointer(X_Dpy, cc->win, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, None, Conf.cursor[CF_RESIZE], CurrentTime) != GrabSuccess) return; menu_windraw(sc, cc->win, "%4d x %-4d", cc->dim.w, cc->dim.h); for (;;) { XWindowEvent(X_Dpy, cc->win, MOUSEMASK, &ev); switch (ev.type) { case MotionNotify: /* not more than 60 times / second */ if ((ev.xmotion.time - ltime) <= (1000 / 60)) continue; ltime = ev.xmotion.time; cc->geom.w = ev.xmotion.x; cc->geom.h = ev.xmotion.y; client_applysizehints(cc); client_resize(cc, 1); menu_windraw(sc, cc->win, "%4d x %-4d", cc->dim.w, cc->dim.h); break; case ButtonRelease: client_resize(cc, 1); XUnmapWindow(X_Dpy, sc->menu.win); XReparentWindow(X_Dpy, sc->menu.win, sc->rootwin, 0, 0); XUngrabPointer(X_Dpy, CurrentTime); /* Make sure the pointer stays within the window. */ if (cc->ptr.x > cc->geom.w) cc->ptr.x = cc->geom.w - cc->bwidth; if (cc->ptr.y > cc->geom.h) cc->ptr.y = cc->geom.h - cc->bwidth; client_ptrwarp(cc); return; } } /* NOTREACHED */ }
/** Manage _NET_WM_STATE_* ewmh */ void ewmh_manage_net_wm_state(long data_l[], Client *c) { /* Manage _NET_WM_STATE_FULLSCREEN */ if(data_l[1] == (long)net_atom[net_wm_state_fullscreen]) { if(data_l[0] == _NET_WM_STATE_ADD && !(c->flags & FSSFlag)) { c->screen = screen_get_with_geo(c->geo.x, c->geo.y); c->flags &= ~UnmapFlag; XMapWindow(dpy, c->win); XReparentWindow(dpy, c->win, ROOT, spgeo[c->screen].x, spgeo[c->screen].y); XResizeWindow(dpy, c->win, spgeo[c->screen].width, spgeo[c->screen].height); XChangeProperty(dpy, c->win, net_atom[net_wm_state], XA_ATOM, 32, PropModeReplace, (uchar *)&net_atom[net_wm_state_fullscreen], 1); c->tmp_geo = c->geo; if(c->flags & FreeFlag) c->ogeo = c->geo; c->flags |= (FSSFlag | MaxFlag); client_raise(c); client_focus(c); XUnmapWindow(dpy, c->frame); } else if(data_l[0] == _NET_WM_STATE_REMOVE && (c->flags & FSSFlag)) { XChangeProperty(dpy, c->win, net_atom[net_wm_state], XA_ATOM, 32, PropModeReplace, (uchar *)0, 0); c->flags &= ~(FSSFlag | MaxFlag); client_map(c); XReparentWindow(dpy, c->win, c->frame, BORDH, TBARH); client_moveresize(c, c->tmp_geo, False); } } /* Manage _NET_WM_STATE_STICKY */ else if(data_l[1] == (long)net_atom[net_wm_state_sticky]) { /* == client_ignore_tag */ c->tag = MAXTAG + 1; arrange(c->screen, True); } /* Manage _NET_WM_STATE_DEMANDS_ATTENTION */ else if(data_l[1] == (long)net_atom[net_wm_state_demands_attention]) { if(data_l[0] == _NET_WM_STATE_ADD) client_urgent(c, True); if(data_l[0] == _NET_WM_STATE_REMOVE) if(c == sel) client_focus(NULL); } return; }
int raise_command(int argc, char** argv, GString* output) { Window win; HSClient* client = NULL; win = string_to_client((argc > 1) ? argv[1] : "", &client); if (client) { client_raise(client); } else { XRaiseWindow(g_display, win); } return 0; }
void mousefunc_client_resize(struct client_ctx *cc, union arg *arg) { XEvent ev; Time ltime = 0; struct screen_ctx *sc = cc->sc; int x = cc->geom.x, y = cc->geom.y; if (cc->flags & CLIENT_FREEZE) return; client_raise(cc); client_ptrsave(cc); if (xu_ptr_grab(cc->win, MOUSEMASK, Conf.cursor[CF_RESIZE]) < 0) return; xu_ptr_setpos(cc->win, cc->geom.w, cc->geom.h); mousefunc_sweep_draw(cc); for (;;) { XMaskEvent(X_Dpy, MOUSEMASK, &ev); switch (ev.type) { case MotionNotify: mousefunc_sweep_calc(cc, x, y, ev.xmotion.x_root, ev.xmotion.y_root); /* don't resize more than 60 times / second */ if ((ev.xmotion.time - ltime) > (1000 / 60)) { ltime = ev.xmotion.time; client_resize(cc, 1); mousefunc_sweep_draw(cc); } break; case ButtonRelease: if (ltime) client_resize(cc, 1); XUnmapWindow(X_Dpy, sc->menuwin); XReparentWindow(X_Dpy, sc->menuwin, sc->rootwin, 0, 0); xu_ptr_ungrab(); /* Make sure the pointer stays within the window. */ if (cc->ptr.x > cc->geom.w) cc->ptr.x = cc->geom.w - cc->bwidth; if (cc->ptr.y > cc->geom.h) cc->ptr.y = cc->geom.h - cc->bwidth; client_ptrwarp(cc); return; } } /* NOTREACHED */ }
/** The map request event handler. * \param ev The event. */ static void event_handle_maprequest(xcb_map_request_event_t *ev) { client_t *c; xcb_get_window_attributes_cookie_t wa_c; xcb_get_window_attributes_reply_t *wa_r; xcb_get_geometry_cookie_t geom_c; xcb_get_geometry_reply_t *geom_r; wa_c = xcb_get_window_attributes_unchecked(globalconf.connection, ev->window); if(!(wa_r = xcb_get_window_attributes_reply(globalconf.connection, wa_c, NULL))) return; if(wa_r->override_redirect) goto bailout; if(xembed_getbywin(&globalconf.embedded, ev->window)) { xcb_map_window(globalconf.connection, ev->window); xembed_window_activate(globalconf.connection, ev->window); } else if((c = client_getbywin(ev->window))) { /* Check that it may be visible, but not asked to be hidden */ if(client_on_selected_tags(c) && !c->hidden) { lua_State *L = globalconf_get_lua_State(); luaA_object_push(L, c); client_set_minimized(L, -1, false); lua_pop(L, 1); /* it will be raised, so just update ourself */ client_raise(c); } } else { geom_c = xcb_get_geometry_unchecked(globalconf.connection, ev->window); if(!(geom_r = xcb_get_geometry_reply(globalconf.connection, geom_c, NULL))) { goto bailout; } client_manage(ev->window, geom_r, wa_r); p_delete(&geom_r); } bailout: p_delete(&wa_r); }
void mousefunc_client_move(struct client_ctx *cc, union arg *arg) { XEvent ev; Time ltime = 0; struct screen_ctx *sc = cc->sc; struct geom xine; int px, py; client_raise(cc); if (cc->flags & CLIENT_FREEZE) return; if (xu_ptr_grab(cc->win, MOUSEMASK, Conf.cursor[CF_MOVE]) < 0) return; xu_ptr_getpos(cc->win, &px, &py); for (;;) { XMaskEvent(X_Dpy, MOUSEMASK, &ev); switch (ev.type) { case MotionNotify: cc->geom.x = ev.xmotion.x_root - px - cc->bwidth; cc->geom.y = ev.xmotion.y_root - py - cc->bwidth; xine = screen_find_xinerama(sc, cc->geom.x + cc->geom.w / 2, cc->geom.y + cc->geom.h / 2, CWM_GAP); cc->geom.x += client_snapcalc(cc->geom.x, cc->geom.x + cc->geom.w + (cc->bwidth * 2), xine.x, xine.x + xine.w, sc->snapdist); cc->geom.y += client_snapcalc(cc->geom.y, cc->geom.y + cc->geom.h + (cc->bwidth * 2), xine.y, xine.y + xine.h, sc->snapdist); /* don't move more than 60 times / second */ if ((ev.xmotion.time - ltime) > (1000 / 60)) { ltime = ev.xmotion.time; client_move(cc); } break; case ButtonRelease: if (ltime) client_move(cc); xu_ptr_ungrab(); return; } } /* NOTREACHED */ }
void buttonpress(XEvent* event) { XButtonEvent* be = &(event->xbutton); HSDebug("name is: ButtonPress on sub %lx, win %lx\n", be->subwindow, be->window); if (mouse_binding_find(be->state, be->button)) { mouse_start_drag(event); } else { focus_window(be->window, false, true); if (*g_raise_on_click) { HSClient* client = get_client_from_window(be->window); if (client) { client_raise(client); } } } XAllowEvents(g_display, ReplayPointer, be->time); }
void sweep(Client *c) { XEvent ev; int old_cx = c->x; int old_cy = c->y; if (!grab_pointer(c->screen->root, MouseMask, resize_curs)) return; client_raise(c); #ifdef INFOBANNER_MOVERESIZE create_info_window(c); #endif XGrabServer(dpy); draw_outline(c); setmouse(c->window, c->width, c->height); for (;;) { XMaskEvent(dpy, MouseMask, &ev); switch (ev.type) { case MotionNotify: if (ev.xmotion.root != c->screen->root) break; draw_outline(c); /* clear */ XUngrabServer(dpy); recalculate_sweep(c, old_cx, old_cy, ev.xmotion.x, ev.xmotion.y, ev.xmotion.state & altmask); #ifdef INFOBANNER_MOVERESIZE update_info_window(c); #endif XSync(dpy, False); XGrabServer(dpy); draw_outline(c); break; case ButtonRelease: draw_outline(c); /* clear */ XUngrabServer(dpy); #ifdef INFOBANNER_MOVERESIZE remove_info_window(); #endif XUngrabPointer(dpy, CurrentTime); moveresize(c); /* In case maximise state has changed: */ ewmh_set_net_wm_state(c); return; default: break; } } }
void window_focus(Window window) { HSClient* client = get_client_from_window(window); assert(client != NULL); // set keyboard focus if (!client->neverfocus) { XSetInputFocus(g_display, window, RevertToPointerRoot, CurrentTime); } else client_sendevent(client, g_wmatom[WMTakeFocus]); if (window != lastfocus) { /* FIXME: this is a workaround because window_focus always is called * twice. see BUGS for more information * * only emit the hook if the focus *really* changes */ // unfocus last one window_unfocus(lastfocus); hsobject_link(g_client_object, &client->object, "focus"); ewmh_update_active_window(window); tag_update_each_focus_layer(); char* title = client ? client->title->str : "?"; char winid_str[STRING_BUF_SIZE]; snprintf(winid_str, STRING_BUF_SIZE, "0x%x", (unsigned int)window); hook_emit_list("focus_changed", winid_str, title, NULL); } // change window-colors HSDebug("window_focus ACTIVE\n"); window_update_border(window, g_window_border_active_color); lastfocus = window; /* do some specials for the max layout */ bool is_max_layout = frame_focused_window(g_cur_frame) == window && g_cur_frame->content.clients.layout == LAYOUT_MAX && get_current_monitor()->tag->floating == false; if (*g_raise_on_focus || is_max_layout) { client_raise(client); } tag_update_focus_layer(get_current_monitor()->tag); grab_client_buttons(get_client_from_window(window), true); client_set_urgent(client, false); }
void sweep(Client *c) { XEvent ev; int old_cx = client_to_Xcoord(c,x); int old_cy = client_to_Xcoord(c,y); if (!grab_pointer(c->screen->root, MouseMask, resize_curs)) return; client_raise(c); annotate_create(c, &annotate_sweep_ctx); setmouse(c->window, c->width, c->height); for (;;) { XMaskEvent(dpy, MouseMask, &ev); switch (ev.type) { case MotionNotify: if (ev.xmotion.root != c->screen->root) break; annotate_preupdate(c, &annotate_sweep_ctx); /* perform recalculate_sweep in Xcoordinates, then convert * back relative to the current phy */ recalculate_sweep(c, old_cx, old_cy, ev.xmotion.x, ev.xmotion.y, ev.xmotion.state & altmask); c->nx -= c->phy->xoff; c->ny -= c->phy->yoff; client_calc_cog(c); client_calc_phy(c); annotate_update(c, &annotate_sweep_ctx); break; case ButtonRelease: annotate_remove(c, &annotate_sweep_ctx); client_calc_phy(c); XUngrabPointer(dpy, CurrentTime); moveresizeraise(c); /* In case maximise state has changed: */ ewmh_set_net_wm_state(c); return; default: break; } } }
void mousefunc_client_move(void *ctx, union arg *arg, enum xev xev) { struct client_ctx *cc = ctx; XEvent ev; Time ltime = 0; struct screen_ctx *sc = cc->sc; struct geom area; int px, py; client_raise(cc); if (cc->flags & CLIENT_FREEZE) return; xu_ptr_getpos(cc->win, &px, &py); if (px < 0) px = 0; else if (px > cc->geom.w) px = cc->geom.w; if (py < 0) py = 0; else if (py > cc->geom.h) py = cc->geom.h; xu_ptr_setpos(cc->win, px, py); if (XGrabPointer(X_Dpy, cc->win, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, None, Conf.cursor[CF_MOVE], CurrentTime) != GrabSuccess) return; menu_windraw(sc, cc->win, "%4d, %-4d", cc->geom.x, cc->geom.y); for (;;) { XWindowEvent(X_Dpy, cc->win, MOUSEMASK, &ev); switch (ev.type) { case MotionNotify: /* not more than 60 times / second */ if ((ev.xmotion.time - ltime) <= (1000 / 60)) continue; ltime = ev.xmotion.time; cc->geom.x = ev.xmotion.x_root - px - cc->bwidth; cc->geom.y = ev.xmotion.y_root - py - cc->bwidth; area = screen_area(sc, cc->geom.x + cc->geom.w / 2, cc->geom.y + cc->geom.h / 2, CWM_GAP); cc->geom.x += client_snapcalc(cc->geom.x, cc->geom.x + cc->geom.w + (cc->bwidth * 2), area.x, area.x + area.w, sc->snapdist); cc->geom.y += client_snapcalc(cc->geom.y, cc->geom.y + cc->geom.h + (cc->bwidth * 2), area.y, area.y + area.h, sc->snapdist); client_move(cc); menu_windraw(sc, cc->win, "%4d, %-4d", cc->geom.x, cc->geom.y); break; case ButtonRelease: client_move(cc); XUnmapWindow(X_Dpy, sc->menu.win); XReparentWindow(X_Dpy, sc->menu.win, sc->rootwin, 0, 0); XUngrabPointer(X_Dpy, CurrentTime); return; } } /* NOTREACHED */ }
bool ewmh_handle_event(XEvent *ev) { client *c; int i, j, xo, yo; long extents[4]; Atom rt; int rf; unsigned long nir, bar; switch(ev->type) { case ClientMessage: c = owner(ev->xclient.window); if(ev->xclient.message_type == ewmh_atoms[NET_WM_MOVERESIZE]) { if(c) { #ifdef DEBUG_EVENTS printf(NAME ": ewmh_handle_event(): handling ClientMessage event\n\tatom: _NET_WM_MOVERESIZE\n"); #endif if(ev->xclient.data.l[2] == NET_WM_MOVERESIZE_MOVE || ev->xclient.data.l[2] == NET_WM_MOVERESIZE_MOVE_KEYBOARD) { client_focus(c, true); xo = client_width_total_intern(c) / 2; yo = client_height_total_intern(c) / 2; XWarpPointer(dpy, None, c->parent, 0, 0, 0, 0, xo, yo); drag_start(A_MOVE, AnyButton, client_x(c) + xo, client_y(c) + yo); } if(ev->xclient.data.l[2] == NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT || ev->xclient.data.l[2] == NET_WM_MOVERESIZE_SIZE_KEYBOARD) { client_focus(c, true); drag_start(A_RESIZE, AnyButton, ev->xclient.data.l[0], ev->xclient.data.l[1]); } } return true; } if(ev->xclient.message_type == ewmh_atoms[NET_CLOSE_WINDOW]) { if(c) { #ifdef DEBUG_EVENTS printf(NAME ": ewmh_handle_event(): handling ClientMessage event\n\tatom: _NET_CLOSE_WINDOW\n"); #endif delete_window(c); } return true; } if(ev->xclient.message_type == ewmh_atoms[NET_ACTIVE_WINDOW]) { if(c) { #ifdef DEBUG_EVENTS printf(NAME ": ewmh_handle_event(): handling ClientMessage event\n\tatom: _NET_ACTIVE_WINDOW\n"); #endif if(c->flags & ICONIC) client_restore(c); else { if(c->desktop != desktop && c->desktop != STICKY) desktop_goto(c->desktop); client_raise(c); } if(evh != wlist_handle_event) client_focus(c, true); } return true; } if(ev->xclient.message_type == ewmh_atoms[NET_RESTACK_WINDOW]) { if(c && ev->xclient.data.l[1] == None) { #ifdef DEBUG_EVENTS printf(NAME ": ewmh_handle_event(): handling ClientMessage event\n\tatom: _NET_RESTACK_WINDOW\n"); #endif client_raise(c); } /* schould also add code for handling this when a sibling window is passed */ /* but we schould find/create a way to test this first */ return true; } if(ev->xclient.message_type == ewmh_atoms[NET_WM_STATE]) { if(c) { #ifdef DEBUG_EVENTS printf(NAME ": ewmh_handle_event(): handling ClientMessage event\n\tatom: _NET_WM_STATE\n"); #endif j = 0; for(i = 1; i < 3; i++) { if(((Atom) ev->xclient.data.l[i]) == ewmh_atoms[NET_WM_STATE_MAXIMIZED_HORZ]) j |= MAXIMIZED_L | MAXIMIZED_R; if(((Atom) ev->xclient.data.l[i]) == ewmh_atoms[NET_WM_STATE_MAXIMIZED_VERT]) j |= MAXIMIZED_T | MAXIMIZED_B; } if(j) client_toggle_state(c, j); if(((Atom) ev->xclient.data.l[1]) == ewmh_atoms[NET_WM_STATE_FULLSCREEN] && (ev->xclient.data.l[0] == NET_WM_STATE_TOGGLE || (ev->xclient.data.l[0] == NET_WM_STATE_ADD && !(c->flags & FULLSCREEN)) || (ev->xclient.data.l[0] == NET_WM_STATE_REMOVE && (c->flags & FULLSCREEN)))) client_fullscreen(c); if(((Atom) ev->xclient.data.l[1]) == ewmh_atoms[NET_WM_STATE_ABOVE]) { if(((Atom) ev->xclient.data.l[0]) == ewmh_atoms[NET_WM_STATE_ADD]) client_set_layer(c, TOP); if(((Atom) ev->xclient.data.l[0]) == ewmh_atoms[NET_WM_STATE_REMOVE] && c->layer == TOP) client_set_layer(c, NORMAL); if(((Atom) ev->xclient.data.l[0]) == ewmh_atoms[NET_WM_STATE_TOGGLE]) client_set_layer(c, (c->layer == TOP) ? NORMAL : TOP); } if(((Atom) ev->xclient.data.l[1]) == ewmh_atoms[NET_WM_STATE_BELOW]) { if(((Atom) ev->xclient.data.l[0]) == ewmh_atoms[NET_WM_STATE_ADD]) client_set_layer(c, BOTTOM); if(((Atom) ev->xclient.data.l[0]) == ewmh_atoms[NET_WM_STATE_REMOVE] && c->layer == BOTTOM) client_set_layer(c, NORMAL); if(((Atom) ev->xclient.data.l[0]) == ewmh_atoms[NET_WM_STATE_TOGGLE]) client_set_layer(c, (c->layer == BOTTOM) ? NORMAL : BOTTOM); } return true; } } if(ev->xclient.message_type == ewmh_atoms[NET_CURRENT_DESKTOP]) { #ifdef DEBUG_EVENTS printf(NAME ": ewmh_handle_event(): handling ClientMessage event\n\tatom: _NET_CURRENT_DESKTOP\n"); #endif desktop_goto(ev->xclient.data.l[0]); return true; } if(ev->xclient.message_type == ewmh_atoms[NET_WM_DESKTOP]) { if(c && ev->xclient.data.l[0] >= STICKY) { #ifdef DEBUG_EVENTS printf(NAME ": ewmh_handle_event(): handling ClientMessage event\n\tatom: _NET_WM_DESKTOP\n"); #endif client_to_desktop(c, (ev->xclient.data.l[0] <= dc) ? ev->xclient.data.l[0] : dc - 1); } return true; } if(ev->xclient.message_type == ewmh_atoms[NET_REQUEST_FRAME_EXTENTS]) { #ifdef DEBUG_EVENTS printf(NAME ": ewmh_handle_event(): handling ClientMessage event\n\tatom: _NET_REQUEST_FRAME_EXTENTS\n"); #endif extents[0] = border_width; extents[1] = border_width; extents[2] = border_width + title_height; extents[3] = border_width; XChangeProperty(dpy, ev->xclient.window, ewmh_atoms[NET_FRAME_EXTENTS], XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &extents, 4); return true; } if(ev->xclient.message_type == ewmh_atoms[NET_SHOWING_DESKTOP]) { #ifdef DEBUG_EVENTS printf(NAME ": ewmh_handle_event(): handling ClientMessage event\n\tatom: _NET_SHOWING_DESKTOP\n"); #endif client_iconify_all(); return true; } break; case PropertyNotify: if(ev->xproperty.atom == ewmh_atoms[NET_WM_STRUT_PARTIAL] || ev->xproperty.atom == ewmh_atoms[NET_WM_STRUT]) { #ifdef DEBUG_EVENTS printf(NAME ": ewmh_handle_event(): handling PropertyNotify event (_NET_WM_STRUT or _NET_WM_STRUT_PARTIAL changed)\n"); #endif ewmh_update_strut(); return true; } c = owner(ev->xproperty.window); if(c && ev->xproperty.atom == ewmh_atoms[NET_WM_NAME]) { if(XGetWindowProperty(dpy, c->window, ewmh_atoms[NET_WM_NAME], 0, 1024, False, xa_utf8_string, &rt, &rf, &nir, &bar, (unsigned char **) &c->ewmh_name) != Success) c->ewmh_name = NULL; else client_update_name(c); return true; } break; } return false; }
/** ButtonPress handle event * \param ev XButtonEvent pointer */ static void buttonpress(XButtonEvent *ev) { Client *c; int i, j, n; screen_get_sel(); /* If the mouse is on a not selected client and you click on it. */ if(((c = client_gb_win(ev->window)) || (c = client_gb_titlebar(ev->window))) && c != sel && (ev->button == Button1 || ev->button == Button2 || ev->button == Button3)) { client_focus(c); client_raise(c); return; } /* Titlebar */ if((c = client_gb_titlebar(ev->window)) && c == sel) for(i = 0; i < conf.titlebar.nmouse; ++i) if(ev->button == conf.titlebar.mouse[i].button) if(conf.titlebar.mouse[i].func) conf.titlebar.mouse[i].func(conf.titlebar.mouse[i].cmd); /* Titlebar buttons */ if((c = client_gb_button(ev->window, &n))) for(i = 0; i < conf.titlebar.button[n].nmouse; ++i) if(ev->button == conf.titlebar.button[n].mouse[i].button) if(conf.titlebar.button[n].mouse[i].func) { client_focus(c); conf.titlebar.button[n].mouse[i].func(conf.titlebar.button[n].mouse[i].cmd); } /* Frame Resize Area */ if((c = client_gb_resize(ev->window))) mouse_resize(c); /* Client */ if((c = client_gb_win(ev->window)) && c == sel) for(i = 0; i < conf.client.nmouse; ++i) if(ev->button == conf.client.mouse[i].button) if(conf.client.mouse[i].func) conf.client.mouse[i].func(conf.client.mouse[i].cmd); /* Root */ if(ev->window == ROOT) for(i = 0; i < conf.root.nmouse; ++i) if(conf.root.mouse[i].tag == seltag[conf.root.mouse[i].screen] || conf.root.mouse[i].tag < 0) if(ev->button == conf.root.mouse[i].button) if(conf.root.mouse[i].func) conf.root.mouse[i].func(conf.root.mouse[i].cmd); /* Infobars */ for(i = 0; i < screen_count(); ++i) if(ev->window == infobar[i].bar->win) for(j = 0; j < conf.bars.nmouse; ++j) if(conf.bars.mouse[j].screen == i || conf.bars.mouse[j].screen < 0) if(conf.bars.mouse[j].tag == seltag[i] || conf.bars.mouse[j].tag < 0) if(ev->button == conf.bars.mouse[j].button) if(conf.bars.mouse[j].func) conf.bars.mouse[j].func(conf.bars.mouse[j].cmd); /* Selbar */ if(conf.bars.selbar && ev->window == infobar[selscreen].selbar->win) for(i = 0; i < conf.selbar.nmouse; ++i) if(conf.selbar.mouse[i].tag == seltag[conf.selbar.mouse[i].screen] || conf.selbar.mouse[i].tag < 0) if(ev->button == conf.selbar.mouse[i].button) if(conf.selbar.mouse[i].func) conf.selbar.mouse[i].func(conf.selbar.mouse[i].cmd); /* Tags */ for(i = 1; i < conf.ntag[selscreen] + 1; ++i) if(ev->window == infobar[selscreen].tags[i]->win) { for(j = 0; j < tags[selscreen][i].nmouse; ++j) if(ev->button == tags[selscreen][i].mouse[j].button) if(tags[selscreen][i].mouse[j].func) tags[selscreen][i].mouse[j].func(tags[selscreen][i].mouse[j].cmd); /* Mouse button action on tag */ if(ev->button == conf.mouse_tag_action[TagSel]) tag_set(i); else if(ev->button == conf.mouse_tag_action[TagTransfert]) tag_transfert(sel, i); else if(ev->button == conf.mouse_tag_action[TagAdd]) tag_additional(selscreen, seltag[selscreen], i); else if(ev->button == conf.mouse_tag_action[TagNext]) tag_set(seltag[selscreen] + 1); else if(ev->button == conf.mouse_tag_action[TagPrev]) tag_set(seltag[selscreen] - 1); } /* Layout button */ if(ev->window == infobar[selscreen].layout_button->win && conf.nlayout > 1) { if(conf.layout_system && (ev->button == Button1 || ev->button == Button3)) /* True -> menu */ { menulayout.y = spgeo[selscreen].y + infobar[selscreen].layout_button->geo.y + INFOBARH; menulayout.x = infobar[selscreen].layout_button->geo.x + (sgeo[selscreen].x - BORDH); if(infobar[selscreen].geo.y != spgeo[selscreen].y) menulayout.y = infobar[selscreen].geo.y - (INFOBARH * menulayout.nitem) - SHADH; uicb_menu("menulayout"); } else { switch(ev->button) { case Button1: case Button4: layoutswitch(True); break; case Button3: case Button5: layoutswitch(False); break; } } } return; }
void layout_magnifier(int screen) { int n = 0; client_t *c, *focus; tag_t **curtags = tags_get_current(screen); area_t geometry, area = screen_area_get(screen, &globalconf.screens[screen].wiboxes, &globalconf.screens[screen].padding, true); focus = globalconf.screens[screen].client_focus; /* Find parent of this window, if it has one. */ if (!IS_TILED(focus, screen) && focus && focus->transient_for) do { focus = focus->transient_for; } while (focus->transient_for != NULL); /* If focused window is not tiled, take the first one which is tiled. */ if(!IS_TILED(focus, screen)) for(focus = globalconf.clients; focus && !IS_TILED(focus, screen); focus = focus->next); /* No windows is tiled, nothing to do. */ if(!focus) goto bailout; for(c = client_list_prev_cycle(&globalconf.clients, focus); c && c != focus; c = client_list_prev_cycle(&globalconf.clients, c)) if(IS_TILED(c, screen) && c != focus) n++; if(n) { geometry.width = area.width * sqrt(curtags[0]->mwfact); geometry.height = area.height * sqrt(curtags[0]->mwfact); geometry.x = area.x + (area.width - geometry.width) / 2; geometry.y = area.y + (area.height - geometry.height) / 2; } else { /* No other clients. */ geometry = area; geometry.width -= 2 * focus->border; geometry.height -= 2 * focus->border; } client_resize(focus, geometry, focus->honorsizehints); client_raise(focus); /* bailout when there is only one window */ if (!n) goto bailout; geometry.x = area.x; geometry.y = area.y; geometry.height = area.height / n; geometry.width = area.width; for(c = client_list_prev_cycle(&globalconf.clients, focus); c && c != focus; c = client_list_prev_cycle(&globalconf.clients, c)) if(IS_TILED(c, screen) && c != focus) { geometry.height -= 2 * c->border; geometry.width -= 2 * c->border; client_resize(c, geometry, c->honorsizehints); geometry.height += 2 * c->border; geometry.width += 2 * c->border; geometry.y += geometry.height; } bailout: p_delete(&curtags); }
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(); } } } }