From df79115dd1d635c46b2d252925d9915b2e2aa107 Mon Sep 17 00:00:00 2001 From: Julien Danjou Date: Thu, 14 Aug 2008 22:16:13 +0200 Subject: [PATCH] zaphod: restore support Signed-off-by: Julien Danjou --- keybinding.c | 12 +++---- lib/awful.lua.in | 7 ++-- lua.c | 61 +++++++++++++++++++++++++++++++++ mouse.c | 87 +++++++++++++++++++++++++++++++++--------------- 4 files changed, 132 insertions(+), 35 deletions(-) diff --git a/keybinding.c b/keybinding.c index 80473aa32..5d471dc87 100644 --- a/keybinding.c +++ b/keybinding.c @@ -82,7 +82,8 @@ keybinding_cmp(const keybinding_t *k1, const keybinding_t *k2) static void window_root_grabkey(keybinding_t *k) { - int phys_screen = globalconf.default_screen; + int phys_screen = 0; + int nscreen = xcb_setup_roots_length(xcb_get_setup(globalconf.connection)); xcb_screen_t *s; xcb_keycode_t kc; @@ -102,8 +103,7 @@ window_root_grabkey(keybinding_t *k) k->mod | globalconf.numlockmask | XCB_MOD_MASK_LOCK, kc, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); phys_screen++; - } while(!globalconf.screens_info->xinerama_is_active - && phys_screen < globalconf.screens_info->nscreen); + } while(phys_screen < nscreen); } /** Ungrab key on the root windows. @@ -112,7 +112,8 @@ window_root_grabkey(keybinding_t *k) static void window_root_ungrabkey(keybinding_t *k) { - int phys_screen = globalconf.default_screen; + int phys_screen = 0; + int nscreen = xcb_setup_roots_length(xcb_get_setup(globalconf.connection)); xcb_screen_t *s; xcb_keycode_t kc; @@ -130,8 +131,7 @@ window_root_ungrabkey(keybinding_t *k) xcb_ungrab_key(globalconf.connection, kc, s->root, k->mod | globalconf.numlockmask | XCB_MOD_MASK_LOCK); phys_screen++; - } while(!globalconf.screens_info->xinerama_is_active - && phys_screen < globalconf.screens_info->nscreen); + } while(phys_screen < nscreen); } static void diff --git a/lib/awful.lua.in b/lib/awful.lua.in index 83598edd6..e335e5e75 100644 --- a/lib/awful.lua.in +++ b/lib/awful.lua.in @@ -18,6 +18,7 @@ local table = table local otable = otable local capi = { + awesome = awesome, screen = screen, client = client, mouse = mouse, @@ -321,7 +322,7 @@ function screen.focus(i) local c = client.focus.history.get(s, 0) if c then capi.client.focus = c end -- Move the mouse on the screen - capi.mouse.coords = capi.screen[s].coords + capi.mouse.screen = s end --- Compare 2 tables of tags. @@ -772,10 +773,10 @@ end --- Spawn a program. -- @param cmd The command. --- @return The os.execute() return value. +-- @return The awesome.spawn return value. function spawn(cmd) if cmd and cmd ~= "" then - return os.execute(cmd .. "&") + return capi.awesome.spawn(cmd .. "&", capi.mouse.screen) end end diff --git a/lua.c b/lua.c index 3168091d8..b03750dbd 100644 --- a/lua.c +++ b/lua.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include @@ -454,6 +456,64 @@ luaA_otable_newindex(lua_State *L) } lua_rawset(L, 1); + + return 0; +} + +/** Spawn a program. + * This function is multi-head (Zaphod) aware and will set display to + * the right screen according to mouse position. + * \param L The Lua VM state. + * \return The number of elements pushed on stack + * \luastack + * \lparam The command to launch. + * \lparam The optional screen number to spawn the command on. + */ +static int +luaA_spawn(lua_State *L) +{ + static const char *shell = NULL; + char display[128], *tmp, newdisplay[128]; + const char *cmd; + int screen = 0; + + if(!shell && !(shell = getenv("SHELL"))) + shell = "/bin/sh"; + + if(lua_gettop(L) == 2) + { + screen = luaL_checknumber(L, 2) - 1; + luaA_checkscreen(screen); + } + + cmd = luaL_checkstring(L, 1); + + if(!globalconf.screens_info->xinerama_is_active + && (tmp = getenv("DISPLAY"))) + { + a_strcpy(display, sizeof(display) - 1, tmp); + if((tmp = strrchr(display, '.'))) + *tmp = '\0'; + snprintf(newdisplay, sizeof(newdisplay) - 1, "%s.%d", display, screen); + setenv("DISPLAY", newdisplay, 1); + } + + /* The double-fork construct avoids zombie processes and keeps the code + * clean from stupid signal handlers. */ + if(fork() == 0) + { + if(fork() == 0) + { + if(globalconf.connection) + xcb_disconnect(globalconf.connection); + setsid(); + execl(shell, shell, "-c", cmd, NULL); + warn("execl '%s -c %s' failed: %s\n", shell, cmd, strerror(errno)); + } + exit(EXIT_SUCCESS); + } + wait(0); + return 0; } @@ -479,6 +539,7 @@ luaA_init(void) { { "quit", luaA_quit }, { "exec", luaA_exec }, + { "spawn", luaA_spawn }, { "restart", luaA_restart }, { "mouse_add", luaA_mouse_add }, { "font_set", luaA_font_set }, diff --git a/mouse.c b/mouse.c index bf8f4d6b5..414399d6e 100644 --- a/mouse.c +++ b/mouse.c @@ -300,8 +300,8 @@ mouse_infobox_new(int phys_screen, int border, area_t geometry, return sw; } -/** Get the Pointer position - * \param window +/** Get the pointer position. + * \param window The window to get position on. * \param x will be set to the Pointer-x-coordinate relative to window * \param y will be set to the Pointer-y-coordinate relative to window * \param mask will be set to the current buttons state @@ -316,7 +316,7 @@ mouse_query_pointer(xcb_window_t window, int *x, int *y, uint16_t *mask) query_ptr_c = xcb_query_pointer_unchecked(globalconf.connection, window); query_ptr_r = xcb_query_pointer_reply(globalconf.connection, query_ptr_c, NULL); - if(!query_ptr_r) + if(!query_ptr_r || !query_ptr_r->same_screen) return false; *x = query_ptr_r->win_x; @@ -329,6 +329,31 @@ mouse_query_pointer(xcb_window_t window, int *x, int *y, uint16_t *mask) return true; } +/** Get the pointer position on the screen. + * \param screen This will be set to the screen number the mouse is on. + * \param x This will be set to the Pointer-x-coordinate relative to window. + * \param y This will be set to the Pointer-y-coordinate relative to window. + * \param mask This will be set to the current buttons state. + * \return True on success, false if an error occured. + */ +static bool +mouse_query_pointer_root(int *s, int *x, int *y, uint16_t *mask) +{ + for(int screen = 0; + screen < xcb_setup_roots_length(xcb_get_setup(globalconf.connection)); + screen++) + { + xcb_window_t root = xutil_screen_get(globalconf.connection, screen)->root; + + if(mouse_query_pointer(root, x, y, mask)) + { + *s = screen; + return true; + } + } + return false; +} + /** Grab the Pointer. * \param window The window grabbed. * \param cursor The cursor to display (see struct.h CurNormal, CurResize, etc). @@ -364,10 +389,10 @@ mouse_ungrab_pointer(void) xcb_ungrab_pointer(globalconf.connection, XCB_CURRENT_TIME); } -/** Set the Pointer position - * \param window the destination window - * \param x x-coordinate inside window - * \param y y-coordinate inside window +/** Set the pointer position. + * \param window The destination window. + * \param x X-coordinate inside window. + * \param y Y-coordinate inside window. */ static inline void mouse_warp_pointer(xcb_window_t window, int x, int y) @@ -421,19 +446,19 @@ mouse_track_mouse_drag(int *x, int *y) } } -/** Get the client that contains the Pointer. +/** Get the client that contains the pointer. * - * \return The client that contains the Pointer or NULL. + * \return The client that contains the pointer or NULL. */ static client_t * -mouse_get_client_under_pointer(void) +mouse_get_client_under_pointer(int phys_screen) { xcb_window_t root; xcb_query_pointer_cookie_t query_ptr_c; xcb_query_pointer_reply_t *query_ptr_r; client_t *c = NULL; - root = xutil_screen_get(globalconf.connection, globalconf.default_screen)->root; + root = xutil_screen_get(globalconf.connection, phys_screen)->root; query_ptr_c = xcb_query_pointer_unchecked(globalconf.connection, root); query_ptr_r = xcb_query_pointer_reply(globalconf.connection, query_ptr_c, NULL); @@ -525,7 +550,7 @@ mouse_client_move(client_t *c, int snap, bool infobox) } /* find client to swap with */ - target = mouse_get_client_under_pointer(); + target = mouse_get_client_under_pointer(c->phys_screen); /* swap position */ if(target && target != c && !target->isfloating) @@ -832,8 +857,10 @@ mouse_client_resize_magnified(client_t *c, bool infobox) maxdist = round(sqrt((area.width*area.width) + (area.height*area.height)) / 2.); - /* get current mouse position */ - mouse_query_pointer(root, &mouse_x, &mouse_y, NULL); + root = xutil_screen_get(globalconf.connection, c->phys_screen)->root; + + if(!mouse_query_pointer(root, &mouse_x, &mouse_y, NULL)) + return; /* select corner */ corner = mouse_snap_to_corner(c->geometry, &mouse_x, &mouse_y, corner); @@ -1070,14 +1097,12 @@ luaA_mouse_index(lua_State *L) const char *attr = luaL_checklstring(L, 2, &len); int mouse_x, mouse_y, i = 0; uint16_t mask; - xcb_window_t root; + int screen; switch(a_tokenize(attr, len)) { case A_TK_COORDS: - root = xutil_screen_get(globalconf.connection, globalconf.default_screen)->root; - - if(!mouse_query_pointer(root, &mouse_x, &mouse_y, &mask)) + if(!mouse_query_pointer_root(&screen, &mouse_x, &mouse_y, &mask)) return 0; lua_newtable(L); @@ -1114,14 +1139,10 @@ luaA_mouse_index(lua_State *L) lua_setfield(L, -2, "buttons"); break; case A_TK_SCREEN: - root = xutil_screen_get(globalconf.connection, globalconf.default_screen)->root; - - if(!mouse_query_pointer(root, &mouse_x, &mouse_y, NULL)) + if(!mouse_query_pointer_root(&screen, &mouse_x, &mouse_y, NULL)) return 0; - i = screen_get_bycoord(globalconf.screens_info, - globalconf.default_screen, - mouse_x, mouse_y); + i = screen_get_bycoord(globalconf.screens_info, screen, mouse_x, mouse_y); lua_pushnumber(L, i + 1); break; @@ -1144,19 +1165,33 @@ luaA_mouse_newindex(lua_State *L) int mouse_x, mouse_y, x, y = 0; uint16_t mask; xcb_window_t root; + int screen, phys_screen; switch(a_tokenize(attr, len)) { case A_TK_COORDS: luaA_checktable(L, 3); - root = xutil_screen_get(globalconf.connection, globalconf.default_screen)->root; - if(!mouse_query_pointer(root, &mouse_x, &mouse_y, &mask)) + if(!mouse_query_pointer_root(&screen, &mouse_x, &mouse_y, &mask)) return 0; x = luaA_getopt_number(L, 3, "x", mouse_x); y = luaA_getopt_number(L, 3, "y", mouse_y); + root = xutil_screen_get(globalconf.connection, screen)->root; + mouse_warp_pointer(root, x, y); + break; + case A_TK_SCREEN: + screen = luaL_checknumber(L, 3) - 1; + luaA_checkscreen(screen); + + /* we need the physical one to get the root window */ + phys_screen = screen_virttophys(screen); + root = xutil_screen_get(globalconf.connection, phys_screen)->root; + + x = globalconf.screens_info->geometry[screen].x; + y = globalconf.screens_info->geometry[screen].y; + mouse_warp_pointer(root, x, y); break; default: