Revert "Replace tags by workspaces"

This reverts commit 00f966ea04.

Revert "[focus] Fix bogus arguments"
This reverts commit 816b5d16bc.

Revert "[mouse] Fix bug with floating"
This reverts commit 89daa72790.

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2008-06-09 21:43:09 +02:00
parent ac1517bacb
commit 1049393840
34 changed files with 1395 additions and 1119 deletions

View File

@ -32,7 +32,7 @@ LAYOUTS += layouts/magnifier.c
LAYOUTS += layouts/magnifier.h
WIDGETS =
WIDGETS += widgets/workspacelist.c
WIDGETS += widgets/taglist.c
WIDGETS += widgets/textbox.c
WIDGETS += widgets/iconbox.c
WIDGETS += widgets/progressbar.c
@ -128,7 +128,7 @@ awesome_SOURCES = \
layout.c layout.h \
keybinding.c keybinding.h \
awesome.c \
workspace.c workspace.h \
tag.c tag.h \
lua.c lua.h \
screen.c screen.h \
statusbar.c statusbar.h \

View File

@ -26,6 +26,7 @@ awesome-client reads commands from standard input.
When you pipe multiple lines into awesome-client, an empty line will flush already
collected lines into awesome with an according immediate execution.
SEE ALSO
--------
awesome(1) awesomerc(5)

View File

@ -26,13 +26,17 @@ regardless of the layout applied. The spiral and dwindle layout are special case
of the tiled layout where the stacking area is arranged in a spiral for the
former or as a rectangular fractal for the later.
Windows are grouped in workspacess.
Windows are grouped by tags. Each window can be tagged with one or multiple
tags. Selecting certain tags displays all windows with these tags.
awesome contains a small status bar which displays all available workspaces,
the layout, the title of the focused window, and a status text.
A floating window is indicated with an empty circle and a maximized
awesome contains a small status bar which displays all available tags, the layout,
the title of the focused window, and a status text. A
floating window is indicated with an empty circle and a maximized
floating window is indicated with a circle square before the windows
title. The selected workspace is indicated with a different color.
title. The selected tags are indicated with a different color. The tags of
the focused window are indicated with a filled square in the top left
corner. The tags which are applied to one or more windows are indicated
with an empty square in the top left corner.
awesome can draw a small border around windows to indicate the focus state.
OPTIONS
@ -46,12 +50,20 @@ OPTIONS
DEFAULTS MOUSE BINDINGS
-----------------------
*Button1* on workspace name::
View workspace.
*Button1* on tag name::
View tag.
*Mod4 + Button1* on tag name::
Tag current client with this tag.
*Button3* on tag name::
Add this tag to current view.
*Mod4 + Button3* on tag name::
Toggle this tag for client.
*Button4*, *Button5* on tag name::
Switch to previous or next tag.
*Button1*, *Button3*, *Button4*, *Button5* on layout symbol::
Switch to previous or next layout.
*Button4*, *Button5* on root window::
Switch to previous or next workspace.
Switch to previous or next tag.
*Mod4 + Button1* on client window::
Move window.
*Mod4 + Button3* on client window::
@ -89,10 +101,12 @@ DEFAULTS KEY BINDINGS
Increase number of columns for non-master windows by 1.
*Mod4 \+ Control \+ l*::
Decrease number of columns for non-master windows by 1.
*Mod4 + Escape*::
View previously selected tag.
*Mod4 + Left*::
View previous workspace.
View previous tag.
*Mod4 + Right*::
View next workspace.
View next tag.
*Mod4 \+ Control \+ space*::
Set client floating.
*Mod4 \+ Shift \+ c*::
@ -102,9 +116,13 @@ DEFAULTS KEY BINDINGS
*Mod4 \+ Control \+ r*::
Restart awesome.
*Mod4 + 1-9*::
Switch to workspace 1-9.
Switch to tag 1-9.
*Mod4 \+ Control \+ 1-9*::
Toggle tag view.
*Mod4 \+ Shift \+ 1-9*::
Move client to workspace 1-9.
Tag client with tag.
*Mod4 \+ Shift \+ Control \+ 1-9*::
Toggle tag on client.
CUSTOMIZATION
-------------

View File

@ -52,6 +52,7 @@
#include "client.h"
#include "focus.h"
#include "ewmh.h"
#include "tag.h"
#include "dbus.h"
#include "statusbar.h"
#include "common/socket.h"

View File

@ -21,25 +21,33 @@ modkey = "Mod4"
layouts = { "tile", "tileleft", "tilebottom", "tiletop", "magnifier", "max", "spiral", "dwindle", "floating" }
-- }}}
-- {{{ Workspaces
-- Define workspaces table
workspaces = {}
-- Create 9 workspaces
for i = 1, 9 do
workspaces[i] = workspace.new({ name = i })
workspaces[i]:add(s)
-- {{{ Tags
-- Define tags table
tags = {}
for s = 1, screen.count() do
-- Each screen has its own tag table
tags[s] = {}
-- Create 9 tags per screen
for tagnumber = 1, 9 do
tags[s][tagnumber] = tag.new({ name = tagnumber })
-- Add tags to screen one by one
tags[s][tagnumber]:add(s)
end
-- I'm sure you want to see at least one tag.
tags[s][1]:view(true)
end
-- I'm sure you want to see at least one workspace
workspaces[1]:screen_set(1)
-- }}}
-- {{{ Statusbar
-- Create a workspacelist widget
myworkspacelist = widget.new({ type = "workspacelist", name = "myworkspacelist" })
myworkspacelist:mouse({ }, 1, function (object, workspace) workspace:screen_set(mouse.screen_get()) end)
myworkspacelist:mouse({ }, 4, awful.workspace.viewnext)
myworkspacelist:mouse({ }, 5, awful.workspace.viewprev)
myworkspacelist:set("text_focus", "<bg color=\"#555555\"/> <title/> ")
-- Create a taglist widget
mytaglist = widget.new({ type = "taglist", name = "mytaglist" })
mytaglist:mouse({}, 1, function (object, tag) awful.tag.viewonly(tag) end)
mytaglist:mouse({ modkey }, 1, function (object, tag) awful.client.toggletag(tag) end)
mytaglist:mouse({}, 3, function (object, tag) tag:view(not tag:isselected()) end)
mytaglist:mouse({ modkey }, 3, function (object, tag) awful.client.toggletag(tag) end)
mytaglist:mouse({ }, 4, awful.tag.viewnext)
mytaglist:mouse({ }, 5, awful.tag.viewprev)
mytaglist:set("text_focus", "<bg color=\"#555555\"/> <title/> ")
-- Create a tasklist widget
mytasklist = widget.new({ type = "tasklist", name = "mytasklist" })
@ -74,7 +82,7 @@ for s = 1, screen.count() do
mystatusbar = statusbar.new({ position = "top", name = "mystatusbar" .. s,
fg = "lightblue", bg = "black" })
-- Add widgets to the statusbar - order matters
mystatusbar:widget_add(myworkspacelist)
mystatusbar:widget_add(mytaglist)
mystatusbar:widget_add(myiconbox)
mystatusbar:widget_add(mytasklist)
mystatusbar:widget_add(mytextbox)
@ -85,8 +93,8 @@ end
-- {{{ Mouse bindings
awesome.mouse({ }, 3, function () awful.spawn(terminal) end)
awesome.mouse({ }, 4, awful.workspace.viewnext)
awesome.mouse({ }, 5, awful.workspace.viewprev)
awesome.mouse({ }, 4, awful.tag.viewnext)
awesome.mouse({ }, 5, awful.tag.viewprev)
client.mouse({ }, 1, function (c) c:focus_set(); c:raise() end)
client.mouse({ modkey }, 1, function (c) c:mouse_move() end)
client.mouse({ modkey }, 3, function (c) c:mouse_resize() end)
@ -96,20 +104,44 @@ client.mouse({ modkey }, 3, function (c) c:mouse_resize() end)
-- Bind keyboard digits
-- Compute the maximum number of digit we need, limited to 9
keynumber = math.min(9, #workspaces);
keynumber = 0
for s = 1, screen.count() do
keynumber = math.min(9, math.max(#tags[s], keynumber));
end
for i = 1, keynumber do
keybinding.new({ modkey }, i,
function ()
workspaces[i]:screen_set(mouse.screen_get())
local screen = mouse.screen_get()
if tags[screen][i] then
awful.tag.viewonly(tags[screen][i])
end
end):add()
keybinding.new({ modkey, "Control" }, i,
function ()
local screen = mouse.screen_get()
if tags[screen][i] then
tags[i]:view(not tags[screen][i]:isselected())
end
end):add()
keybinding.new({ modkey, "Shift" }, i,
function ()
client.focus_get():workspace_set(workspaces[i])
local screen = mouse.screen_get()
if tags[screen][i] then
awful.client.movetotag(tags[screen][i])
end
end):add()
keybinding.new({ modkey, "Control", "Shift" }, i,
function ()
local screen = mouse.screen_get()
if tags[screen][i] then
awful.client.toggletag(tags[screen][i])
end
end):add()
end
keybinding.new({ modkey }, "Left", awful.workspace.viewprev):add()
keybinding.new({ modkey }, "Right", awful.workspace.viewnext):add()
keybinding.new({ modkey }, "Left", awful.tag.viewprev):add()
keybinding.new({ modkey }, "Right", awful.tag.viewnext):add()
-- Standard program
keybinding.new({ modkey }, "Return", function () awful.spawn(terminal) end):add()
@ -129,12 +161,12 @@ keybinding.new({ modkey, "Control" }, "space", awful.client.togglefloating):add(
keybinding.new({ modkey }, "o", awful.client.movetoscreen):add()
-- Layout manipulation
keybinding.new({ modkey }, "l", function () awful.workspace.incmwfact(0.05) end):add()
keybinding.new({ modkey }, "h", function () awful.workspace.incmwfact(-0.05) end):add()
keybinding.new({ modkey, "Shift" }, "h", function () awful.workspace.incnmaster(1) end):add()
keybinding.new({ modkey, "Shift" }, "l", function () awful.workspace.incnmaster(-1) end):add()
keybinding.new({ modkey, "Control" }, "h", function () awful.workspace.incncol(1) end):add()
keybinding.new({ modkey, "Control" }, "l", function () awful.workspace.incncol(1) end):add()
keybinding.new({ modkey }, "l", function () awful.tag.incmwfact(0.05) end):add()
keybinding.new({ modkey }, "h", function () awful.tag.incmwfact(-0.05) end):add()
keybinding.new({ modkey, "Shift" }, "h", function () awful.tag.incnmaster(1) end):add()
keybinding.new({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1) end):add()
keybinding.new({ modkey, "Control" }, "h", function () awful.tag.incncol(1) end):add()
keybinding.new({ modkey, "Control" }, "l", function () awful.tag.incncol(1) end):add()
keybinding.new({ modkey }, "space", function () awful.layout.inc(layouts, 1) end):add()
keybinding.new({ modkey, "Shift" }, "space", function () awful.layout.inc(layouts, -1) end):add()
-- }}}
@ -153,7 +185,7 @@ end
-- Hook function to exeucte when the mouse is over a client.
function hook_mouseover(c)
-- Sloppy focus, but disabled for magnifier layout
if c:workspace_get():layout_get() ~= "magnifier" then
if awful.layout.get(c:screen_get()) ~= "magnifier" then
c:focus_set()
end
end
@ -170,10 +202,10 @@ function hook_newclient(c)
end
-- Hook function to execute when arranging the screen
-- (workspace switch, new client, etc)
function hook_arrange(ws)
local screen = ws:screen_get()
mylayoutbox[screen]:set("image", "@iconsdir@/layouts/" .. ws:layout_get() .. "w.png")
-- (tag switch, new client, etc)
function hook_arrange(screen)
local layout = awful.layout.get(screen)
mylayoutbox[screen]:set("image", "@iconsdir@/layouts/" .. layout .. "w.png")
end
-- Hook called every second

165
awful.lua
View File

@ -20,7 +20,7 @@ local pairs = pairs
local awesome = awesome
local screen = screen
local client = client
local workspace = workspace
local tag = tag
local mouse = mouse
local os = os
local table = table
@ -84,7 +84,13 @@ function client_moveresize(x, y, w, h)
end
function screen_focus(i)
local s = mouse.screen_get()
local sel = client.focus_get()
local s
if sel then
s = sel:screen_get()
else
s = mouse.screen_get()
end
local count = screen.count()
s = s + i
if s < 1 then
@ -92,81 +98,136 @@ function screen_focus(i)
elseif s > count then
s = 1
end
local ws = screen.workspace_get(s)
if ws then
ws:focus_set()
end
screen.focus(s)
-- Move the mouse on the screen
local screen_coords = screen.coords_get(s)
mouse.coords_set(screen_coords['x'], screen_coords['y'])
end
-- Return a table with all visible tags
function tag_selectedlist(s)
local idx = 1
local screen = s or mouse.screen_get()
local tags = tag.get(screen)
local vtags = {}
for i, t in ipairs(tags) do
if t:isselected() then
vtags[idx] = t
idx = idx + 1
end
end
return vtags
end
-- Return only the first element of all visible tags,
-- so that's the first visible tags.
function tag_selected(s)
return tag_selectedlist(s)[1]
end
-- Set master width factor
function workspace_setmwfact(i)
local t = workspace_selected()
function tag_setmwfact(i)
local t = tag_selected()
if t then
t:mwfact_set(i)
end
end
-- Increase master width factor
function workspace_incmwfact(i)
local t = workspace_selected()
function tag_incmwfact(i)
local t = tag_selected()
if t then
t:mwfact_set(t:mwfact_get() + i)
end
end
-- Set number of master windows
function workspace_setnmaster(i)
local t = workspace_selected()
function tag_setnmaster(i)
local t = tag_selected()
if t then
t:nmaster_set(i)
end
end
-- Increase number of master windows
function workspace_incnmaster(i)
local t = workspace_selected()
function tag_incnmaster(i)
local t = tag_selected()
if t then
t:nmaster_set(t:nmaster_get() + i)
end
end
-- Set number of column windows
function workspace_setncol(i)
local t = workspace_selected()
function tag_setncol(i)
local t = tag_selected()
if t then
t:ncol_set(i)
end
end
-- Increase number of column windows
function workspace_incncol(i)
local t = workspace_selected()
function tag_incncol(i)
local t = tag_selected()
if t then
t:ncol_set(t:ncol_get() + i)
end
end
function workspace_viewidx(r)
local workspaces = workspace.get()
local sel = workspace.visible_get(mouse.screen_get())
for i, t in ipairs(workspaces) do
-- View no tag
function tag_viewnone()
local tags = tag.get(mouse.screen_get())
for i, t in ipairs(tags) do
t:view(false)
end
end
function tag_viewidx(r)
local tags = tag.get(mouse.screen_get())
local sel = tag_selected()
tag_viewnone()
for i, t in ipairs(tags) do
if t == sel then
workspaces[array_boundandcycle(workspaces, i + r)]:screen_set(mouse.screen_get())
tags[array_boundandcycle(tags, i + r)]:view(true)
end
end
end
-- View next workspace
function workspace_viewnext()
return workspace_viewidx(1)
-- View next tag
function tag_viewnext()
return tag_viewidx(1)
end
-- View previous workspace
function workspace_viewprev()
return workspace_viewidx(-1)
-- View previous tag
function tag_viewprev()
return tag_viewidx(-1)
end
function tag_viewonly(t)
tag_viewnone()
t:view(true)
end
function tag_viewmore(tags)
tag_viewnone()
for i, t in ipairs(tags) do
t:view(true)
end
end
function client_movetotag(target, c)
local sel = c or client.focus_get();
local tags = tag.get(mouse.screen_get())
for i, t in ipairs(tags) do
sel:tag(t, false)
end
sel:tag(target, true)
end
function client_toggletag(target, c)
local sel = c or client.focus_get();
if sel then
sel:tag(target, not sel:istagged(target))
end
end
function client_togglefloating(c)
@ -189,11 +250,18 @@ function client_movetoscreen(c, s)
end
end
-- Function to change the layout of the current workspace.
function layout_get(screen)
local t = tag_selected(screen)
if t then
return t:layout_get()
end
end
-- Function to change the layout of the current tag.
-- layouts = table of layouts (define in .awesomerc.lua)
-- i = relative index
function layout_inc(layouts, i)
local t = workspace.visible_get(mouse.screen_get())
local t = tag_selected()
local number_of_layouts = 0
local rev_layouts = {}
for i, v in ipairs(layouts) do
@ -201,7 +269,7 @@ function layout_inc(layouts, i)
number_of_layouts = number_of_layouts + 1
end
if t then
local cur_layout = t:layout_get()
local cur_layout = layout_get()
local new_layout_index = (rev_layouts[cur_layout] + i) % number_of_layouts
if new_layout_index == 0 then
new_layout_index = number_of_layouts
@ -210,9 +278,9 @@ function layout_inc(layouts, i)
end
end
-- function to set the layout of the current workspace by name.
-- function to set the layout of the current tag by name.
function layout_set(layout)
local t = workspace.visible_get(mouse.screen_get())
local t = tag_selected()
if t then
t:layout_set(layout)
end
@ -272,24 +340,30 @@ function spawn(cmd)
return os.execute(cmd .. "&")
end
-- Export workspaces function
P.workspace =
-- Export tags function
P.tag =
{
viewprev = workspace_viewprev;
viewnext = workspace_viewnext;
setmwfact = workspace_setmwfact;
incmwfact = workspace_incmwfact;
setncol = workspace_setncol;
incncol = workspace_incncol;
setnmaster = workspace_setnmaster;
incnmaster = workspace_incnmaster;
viewnone = tag_viewnone;
viewprev = tag_viewprev;
viewnext = tag_viewnext;
viewonly = tag_viewonly;
viewmore = tag_viewmore;
setmwfact = tag_setmwfact;
incmwfact = tag_incmwfact;
setncol = tag_setncol;
incncol = tag_incncol;
setnmaster = tag_setnmaster;
incnmaster = tag_incnmaster;
selected = tag_selected;
selectedlist = tag_selectedlist;
}
P.client =
{
next = client_next;
focus = client_focus;
swap = client_swap;
movetoworkspace = client_movetoworkspace;
movetotag = client_movetotag;
toggletag = client_toggletag;
togglefloating = client_togglefloating;
moveresize = client_moveresize;
movetoscreen = client_movetoscreen;
@ -300,6 +374,7 @@ P.screen =
}
P.layout =
{
get = layout_get;
set = layout_set;
inc = layout_inc;
}

294
client.c
View File

@ -27,7 +27,7 @@
#include <xcb/shape.h>
#include "client.h"
#include "workspace.h"
#include "tag.h"
#include "window.h"
#include "focus.h"
#include "ewmh.h"
@ -44,40 +44,40 @@
extern awesome_t globalconf;
/** Load windows properties, restoring client's workspace
/** Load windows properties, restoring client's tag
* and floating state before awesome was restarted if any.
* \todo This may bug if number of workspacess is != than before.
* \todo This may bug if number of tags is != than before.
* \param c A client pointer.
* \param screen A virtual screen number.
* \return True if client had property, false otherwise.
*/
static bool
client_loadprops(client_t * c)
client_loadprops(client_t * c, int screen)
{
int i, nworkspaces = 0;
workspace_t *workspace;
int i, ntags = 0;
tag_t *tag;
char *prop = NULL;
bool result = false;
xutil_intern_atom_request_t atom_q;
atom_q = xutil_intern_atom(globalconf.connection, &globalconf.atoms, "_AWESOME_PROPERTIES");
for(workspace = globalconf.workspaces; workspace; workspace = workspace->next)
nworkspaces++;
for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
ntags++;
if(xutil_gettextprop(globalconf.connection, c->win, &globalconf.atoms,
xutil_intern_atom_reply(globalconf.connection, &globalconf.atoms, atom_q),
xutil_intern_atom_reply(globalconf.connection, &globalconf.atoms,
xutil_intern_atom(globalconf.connection,
&globalconf.atoms,
"_AWESOME_PROPERTIES")),
&prop))
{
for(i = 0, workspace = globalconf.workspaces; workspace && i < nworkspaces && prop[i]; i++, workspace = workspace->next)
for(i = 0, tag = globalconf.screens[screen].tags; tag && i < ntags && prop[i]; i++, tag = tag->next)
if(prop[i] == '1')
{
workspace_client_set(c, workspace);
tag_client(c, tag);
result = true;
break;
}
else
untag_client(c, tag);
/* jump to the end */
i = nworkspaces;
if(prop[i])
client_setfloating(c, prop[i] == '1',
(prop[i + 1] >= 0 && prop[i + 1] <= LAYER_FULLSCREEN) ? atoi(&prop[i + 1]) : prop[i] == '1' ? LAYER_FLOAT : LAYER_TILE);
@ -115,42 +115,43 @@ window_isprotodel(xcb_window_t win)
return ret;
}
/** Returns true if a client is on a workspace visible
/** Returns true if a client is tagged with one of the tags visibl
* on any screen.
* \param c The client.
* \return True if client is visible, false otherwise.
* \return True if client is tagged, false otherwise.
*/
static bool
client_isvisible_anyscreen(client_t *c)
{
workspace_t *ws;
tag_t *tag;
int screen;
if(c && !c->ishidden)
{
ws = workspace_client_get(c);
for(screen = 0; screen < globalconf.screens_info->nscreen; screen++)
if(globalconf.screens[screen].workspace == ws)
return true;
}
for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
if(tag->selected && is_client_tagged(c, tag))
return true;
return false;
}
/** Returns true if a client is on the workspace visible on the specified
* screen.
/** Returns true if a client is tagged
* with one of the tags of the specified screen.
* \param c The client to check.
* \param screen Virtual screen number.
* \return True if the client is visible, false otherwise.
* \return true if the client is visible, false otherwise.
*/
bool
client_isvisible(client_t *c, int screen)
{
if(c && !c->ishidden)
return (workspace_client_get(c) == globalconf.screens[screen].workspace);
tag_t *tag;
if(c && !c->ishidden && c->screen == screen)
for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
if(tag->selected && is_client_tagged(c, tag))
return true;
return false;
}
/** Get a client by its window.
* \param w The client window to find.
* \return A client pointer if found, NULL otherwise.
@ -193,18 +194,18 @@ client_updatetitle(client_t *c)
luaA_client_userdata_new(c);
luaA_dofunction(globalconf.L, globalconf.hooks.titleupdate, 1);
widget_invalidate_cache(WIDGET_CACHE_CLIENTS);
widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
}
static void
client_unfocus(client_t *c)
{
/* Call hook */
luaA_client_userdata_new(c);
luaA_client_userdata_new(globalconf.focus->client);
luaA_dofunction(globalconf.L, globalconf.hooks.unfocus, 1);
focus_client_push(NULL);
widget_invalidate_cache(WIDGET_CACHE_CLIENTS);
widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
}
/** Ban client and unmap it
@ -223,40 +224,55 @@ client_ban(client_t *c)
/** Give focus to client, or to first client if client is NULL,
* \param c The client or NULL.
* \return True if a window (even root).
* \param screen Virtual screen number.
* \return True if a window (even root) has received focus, false otherwise.
*/
bool
client_focus(client_t *c)
client_focus(client_t *c, int screen)
{
int phys_screen;
if(!c)
return false;
/* if c is NULL or invisible, take next client in the focus history */
if((!c || (c && (!client_isvisible(c, screen))))
&& !(c = focus_get_current_client(screen)))
/* if c is still NULL take next client in the stack */
for(c = globalconf.clients; c && (c->skip || !client_isvisible(c, screen)); c = c->next);
/* unfocus current selected client */
if(globalconf.focus->client)
client_unfocus(globalconf.focus->client);
/* unban the client before focusing or it will fail */
client_unban(c);
/* save sel in focus history */
focus_client_push(c);
xcb_set_input_focus(globalconf.connection, XCB_INPUT_FOCUS_POINTER_ROOT,
c->win, XCB_CURRENT_TIME);
/* since we're dropping EnterWindow events and sometimes the window
* will appear under the mouse, grabbuttons */
window_grabbuttons(c->win, c->phys_screen);
phys_screen = c->phys_screen;
if(c)
{
/* unban the client before focusing or it will fail */
client_unban(c);
/* save sel in focus history */
focus_client_push(c);
xcb_set_input_focus(globalconf.connection, XCB_INPUT_FOCUS_POINTER_ROOT,
c->win, XCB_CURRENT_TIME);
/* since we're dropping EnterWindow events and sometimes the window
* will appear under the mouse, grabbuttons */
window_grabbuttons(c->win, c->phys_screen);
phys_screen = c->phys_screen;
/* Some layouts use focused client differently, so call them back. */
workspace_client_get(c)->need_arrange = true;
/* Some layouts use focused client differently, so call them back. */
globalconf.screens[c->screen].need_arrange = true;
/* execute hook */
luaA_client_userdata_new(globalconf.focus->client);
luaA_dofunction(globalconf.L, globalconf.hooks.focus, 1);
/* execute hook */
luaA_client_userdata_new(globalconf.focus->client);
luaA_dofunction(globalconf.L, globalconf.hooks.focus, 1);
}
else
{
phys_screen = screen_virttophys(screen);
xcb_set_input_focus(globalconf.connection,
XCB_INPUT_FOCUS_POINTER_ROOT,
xcb_aux_get_screen(globalconf.connection, phys_screen)->root,
XCB_CURRENT_TIME);
}
ewmh_update_net_active_window(phys_screen);
widget_invalidate_cache(WIDGET_CACHE_CLIENTS);
widget_invalidate_cache(screen, WIDGET_CACHE_CLIENTS);
return true;
}
@ -312,20 +328,20 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int screen)
client_t *c, *t = NULL;
xcb_window_t trans;
bool rettrans, retloadprops;
tag_t *tag;
xcb_size_hints_t *u_size_hints;
int rscreen;
const uint32_t select_input_val[] = {
XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE |
XCB_EVENT_MASK_ENTER_WINDOW };
c = p_new(client_t, 1);
rscreen = screen_get_bycoord(globalconf.screens_info, screen, wgeom->x, wgeom->y);
c->screen = screen_get_bycoord(globalconf.screens_info, screen, wgeom->x, wgeom->y);
if(globalconf.screens_info->xinerama_is_active)
c->phys_screen = globalconf.default_screen;
else
c->phys_screen = rscreen;
c->phys_screen = c->screen;
/* Initial values */
c->win = w;
@ -341,16 +357,18 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int screen)
client_updatewmhints(c);
/* Try to load props if any */
if(!(retloadprops = client_loadprops(c)))
workspace_client_set(c, globalconf.screens[screen].workspace);
if(!(retloadprops = client_loadprops(c, screen)))
screen_client_moveto(c, screen, true);
/* Then check clients hints */
ewmh_check_client_hints(c);
/* check for transient and set on same workspace like its parent */
/* check for transient and set tags like its parent */
if((rettrans = xutil_get_transient_for_hint(globalconf.connection, w, &trans))
&& (t = client_getbywin(trans)))
workspace_client_set(c, workspace_client_get(t));
for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next)
if(is_client_tagged(t, tag))
tag_client(c, tag);
/* should be floating if transsient or fixed */
if(rettrans || c->isfixed)
@ -388,7 +406,7 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int screen)
/* Push client in stack */
stack_client_push(c);
widget_invalidate_cache(WIDGET_CACHE_CLIENTS);
widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
ewmh_update_net_client_list(c->phys_screen);
/* update window title */
@ -455,16 +473,15 @@ client_geometry_hints(client_t *c, area_t geometry)
bool
client_resize(client_t *c, area_t geometry, bool hints)
{
int screen, new_screen;
workspace_t *ws;
int new_screen;
area_t area;
layout_t *layout = layout_get_current(c->screen);
bool resized = false;
/* Values to configure a window is an array where values are
* stored according to 'value_mask' */
uint32_t values[5];
ws = workspace_client_get(c);
if(c->titlebar && !c->ismoving && !c->isfloating && ws->layout != layout_floating)
if(c->titlebar && !c->ismoving && !c->isfloating && layout != layout_floating)
{
titlebar_update_geometry(c, geometry);
geometry = titlebar_geometry_remove(c->titlebar, geometry);
@ -476,12 +493,24 @@ client_resize(client_t *c, area_t geometry, bool hints)
if(geometry.width <= 0 || geometry.height <= 0)
return false;
/* offscreen appearance fixes */
area = display_area_get(c->phys_screen, NULL,
&globalconf.screens[c->screen].padding);
if(geometry.x > area.width)
geometry.x = area.width - geometry.width - 2 * c->border;
if(geometry.y > area.height)
geometry.y = area.height - geometry.height - 2 * c->border;
if(geometry.x + geometry.width + 2 * c->border < 0)
geometry.x = 0;
if(geometry.y + geometry.height + 2 * c->border < 0)
geometry.y = 0;
if(c->geometry.x != geometry.x || c->geometry.y != geometry.y
|| c->geometry.width != geometry.width || c->geometry.height != geometry.height)
{
screen = workspace_screen_get(ws);
new_screen =
screen_get_bycoord(globalconf.screens_info, screen, geometry.x, geometry.y);
screen_get_bycoord(globalconf.screens_info, c->screen, geometry.x, geometry.y);
c->geometry.x = values[0] = geometry.x;
c->geometry.width = values[2] = geometry.width;
@ -492,7 +521,7 @@ client_resize(client_t *c, area_t geometry, bool hints)
/* save the floating geometry if the window is floating but not
* maximized */
if(c->ismoving || c->isfloating
|| ws->layout == layout_floating)
|| layout_get_current(new_screen) == layout_floating)
{
titlebar_update_geometry_floating(c);
if(!c->ismax)
@ -506,12 +535,15 @@ client_resize(client_t *c, area_t geometry, bool hints)
values);
window_configure(c->win, geometry, c->border);
if(c->screen != new_screen)
screen_client_moveto(c, new_screen, false);
resized = true;
}
/* call it again like it was floating,
* we want it to be sticked to the window */
if(!c->ismoving && !c->isfloating && ws->layout != layout_floating)
if(!c->ismoving && !c->isfloating && layout != layout_floating)
titlebar_update_geometry_floating(c);
return resized;
@ -534,8 +566,9 @@ client_setfloating(client_t *c, bool floating, layer_t layer)
c->ismax = false;
client_resize(c, c->m_geometry, false);
}
workspace_client_get(c)->need_arrange = true;
widget_invalidate_cache(WIDGET_CACHE_CLIENTS);
if(client_isvisible(c, c->screen))
globalconf.screens[c->screen].need_arrange = true;
widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
if(floating)
{
c->oldlayer = c->layer;
@ -554,23 +587,20 @@ client_setfloating(client_t *c, bool floating, layer_t layer)
void
client_saveprops(client_t *c)
{
int i = 0, nws = 0;
int i = 0, ntags = 0;
char *prop;
workspace_t *workspace, *cws = workspace_client_get(c);
tag_t *tag;
xutil_intern_atom_request_t atom_q;
atom_q = xutil_intern_atom(globalconf.connection, &globalconf.atoms, "_AWESOME_PROPERTIES");
for(workspace = globalconf.workspaces; workspace; workspace = workspace->next)
nws++;
for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next)
ntags++;
prop = p_new(char, nws + 3);
prop = p_new(char, ntags + 3);
for(workspace = globalconf.workspaces; workspace; workspace = workspace->next, i++)
if(cws == workspace)
prop[i] = '1';
else
prop[i] = '0';
for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next, i++)
prop[i] = is_client_tagged(c, tag) ? '1' : '0';
prop[i] = c->isfloating ? '1' : '0';
@ -597,6 +627,8 @@ client_unban(client_t *c)
void
client_unmanage(client_t *c)
{
tag_t *tag;
/* The server grab construct avoids race conditions. */
xcb_grab_server(globalconf.connection);
@ -608,11 +640,11 @@ client_unmanage(client_t *c)
client_list_detach(&globalconf.clients, c);
focus_client_delete(c);
stack_client_delete(c);
for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next)
untag_client(c, tag);
if(globalconf.focus->client == c)
client_focus(focus_client_getcurrent(workspace_client_get(c)));
workspace_client_remove(c);
client_focus(NULL, c->screen);
xcb_ungrab_button(globalconf.connection, XCB_BUTTON_INDEX_ANY, c->win, ANY_MODIFIER);
window_setstate(c->win, XCB_WM_WITHDRAWN_STATE);
@ -647,7 +679,7 @@ client_updatewmhints(client_t *c)
luaA_client_userdata_new(c);
luaA_dofunction(globalconf.L, globalconf.hooks.urgent, 1);
widget_invalidate_cache(WIDGET_CACHE_CLIENTS);
widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
}
if((wm_hints_flags & XCB_WM_STATE_HINT) &&
(xcb_wm_hints_get_initial_state(wmh) == XCB_WM_WITHDRAWN_STATE))
@ -883,7 +915,7 @@ client_setborder(client_t *c, uint32_t width)
c->border = width;
xcb_configure_window(globalconf.connection, c->win,
XCB_CONFIG_WINDOW_BORDER_WIDTH, &width);
workspace_client_get(c)->need_arrange = true;
globalconf.screens[c->screen].need_arrange = true;
}
/** Set the client border width and color.
@ -908,28 +940,64 @@ luaA_client_border_set(lua_State *L)
return 0;
}
/** Set the client on the specified workspace.
* \param A workspace object.
/** Move the client to another screen.
* \param A screen number.
*/
static int
luaA_client_workspace_set(lua_State *L)
luaA_client_screen_set(lua_State *L)
{
client_t **c = luaA_checkudata(L, 1, "client");
workspace_t **workspace = luaA_checkudata(L, 2, "workspace");
/* arrange old ws */
workspace_client_get(*c)->need_arrange = true;
workspace_client_set(*c, *workspace);
int screen = luaL_checknumber(L, 2) - 1;
luaA_checkscreen(screen);
screen_client_moveto(*c, screen, true);
return 0;
}
/** Get the workspace the client is on.
* \return A workspace.
/** Get the screen number the client is onto.
* \return A screen number.
*/
static int
luaA_client_workspace_get(lua_State *L)
luaA_client_screen_get(lua_State *L)
{
client_t **c = luaA_checkudata(L, 1, "client");
return luaA_workspace_userdata_new(workspace_client_get(*c));
lua_pushnumber(L, 1 + (*c)->screen);
return 1;
}
/** Tag a client with a specified tag.
* \param A tag object.
* \param A boolean value: true to add this tag to clients, false to remove.
*/
static int
luaA_client_tag(lua_State *L)
{
client_t **c = luaA_checkudata(L, 1, "client");
tag_t **tag = luaA_checkudata(L, 2, "tag");
bool tag_the_client = luaA_checkboolean(L, 3);
if((*tag)->screen != (*c)->screen)
luaL_error(L, "tag and client are on different screens");
if(tag_the_client)
tag_client(*c, *tag);
else
untag_client(*c, *tag);
return 0;
}
/** Check if a client is tagged with the specified tag.
* \param A tag object.
* \return A boolean value, true if the client is tagged with this tag, false
* otherwise.
*/
static int
luaA_client_istagged(lua_State *L)
{
client_t **c = luaA_checkudata(L, 1, "client");
tag_t **tag = luaA_checkudata(L, 2, "tag");
lua_pushboolean(L, is_client_tagged(*c, *tag));
return 1;
}
/** Get the client coordinates on the display.
@ -957,7 +1025,7 @@ luaA_client_coords_set(lua_State *L)
client_t **c = luaA_checkudata(L, 1, "client");
area_t geometry;
if((*c)->isfloating || workspace_client_get(*c)->layout == layout_floating)
if((*c)->isfloating || layout_get_current((*c)->screen) == layout_floating)
{
luaA_checktable(L, 2);
geometry.x = luaA_getopt_number(L, 2, "x", (*c)->geometry.x);
@ -995,9 +1063,10 @@ luaA_client_swap(lua_State *L)
client_t **c = luaA_checkudata(L, 1, "client");
client_t **swap = luaA_checkudata(L, 2, "client");
client_list_swap(&globalconf.clients, *swap, *c);
workspace_client_get(*c)->need_arrange = true;
workspace_client_get(*swap)->need_arrange = true;
widget_invalidate_cache(WIDGET_CACHE_CLIENTS);
globalconf.screens[(*c)->screen].need_arrange = true;
globalconf.screens[(*swap)->screen].need_arrange = true;
widget_invalidate_cache((*c)->screen, WIDGET_CACHE_CLIENTS);
widget_invalidate_cache((*swap)->screen, WIDGET_CACHE_CLIENTS);
return 0;
}
@ -1005,7 +1074,7 @@ static int
luaA_client_focus_set(lua_State *L)
{
client_t **c = luaA_checkudata(L, 1, "client");
client_focus(*c);
client_focus(*c, (*c)->screen);
return 0;
}
@ -1121,7 +1190,6 @@ luaA_client_titlebar_set(lua_State *L)
{
client_t **c = luaA_checkudata(L, 1, "client");
titlebar_t **t = luaA_checkudata(L, 2, "titlebar");
workspace_t *ws;
if(client_getbytitlebar(*t))
luaL_error(L, "titlebar is already used by another client");
@ -1135,12 +1203,10 @@ luaA_client_titlebar_set(lua_State *L)
titlebar_ref(t);
titlebar_init(*c);
ws = workspace_client_get(*c);
if((*c)->isfloating || ws->layout == layout_floating)
if((*c)->isfloating || layout_get_current((*c)->screen) == layout_floating)
titlebar_update_geometry_floating(*c);
else
ws->need_arrange = true;
globalconf.screens[(*c)->screen].need_arrange = true;
return 0;
}
@ -1176,7 +1242,7 @@ luaA_client_hide(lua_State *L)
{
client_t **c = luaA_checkudata(L, 1, "client");
(*c)->ishidden = true;
workspace_client_get(*c)->need_arrange = true;
globalconf.screens[(*c)->screen].need_arrange = true;
return 0;
}
@ -1187,7 +1253,7 @@ luaA_client_unhide(lua_State *L)
{
client_t **c = luaA_checkudata(L, 1, "client");
(*c)->ishidden = false;
workspace_client_get(*c)->need_arrange = true;
globalconf.screens[(*c)->screen].need_arrange = true;
return 0;
}
@ -1213,9 +1279,11 @@ const struct luaL_reg awesome_client_meta[] =
{ "titlebar_get", luaA_client_titlebar_get },
{ "name_get", luaA_client_name_get },
{ "name_set", luaA_client_name_set },
{ "screen_set", luaA_client_screen_set },
{ "screen_get", luaA_client_screen_get },
{ "border_set", luaA_client_border_set },
{ "workspace_set", luaA_client_workspace_set },
{ "workspace_get", luaA_client_workspace_get },
{ "tag", luaA_client_tag },
{ "istagged", luaA_client_istagged },
{ "coords_get", luaA_client_coords_get },
{ "coords_set", luaA_client_coords_set },
{ "opacity_set", luaA_client_opacity_set },

View File

@ -28,7 +28,7 @@
bool client_isvisible(client_t *, int);
client_t * client_getbywin(xcb_window_t);
bool client_focus(client_t *);
bool client_focus(client_t *, int);
void client_raise(client_t *);
void client_ban(client_t *);
void client_unban(client_t *);

15
event.c
View File

@ -25,6 +25,7 @@
#include "screen.h"
#include "event.h"
#include "tag.h"
#include "statusbar.h"
#include "window.h"
#include "mouse.h"
@ -33,7 +34,6 @@
#include "widget.h"
#include "titlebar.h"
#include "lua.h"
#include "workspace.h"
#include "layouts/tile.h"
#include "layouts/floating.h"
#include "common/xscreen.h"
@ -146,7 +146,7 @@ event_handle_buttonpress(void *data __attribute__ ((unused)),
if(ev->event_x >= w->area.x && ev->event_x < w->area.x + w->area.width
&& ev->event_y >= w->area.y && ev->event_y < w->area.y + w->area.height)
{
w->widget->button_press(w, ev, workspace_screen_get(workspace_client_get(c)),
w->widget->button_press(w, ev, c->screen,
c->titlebar, AWESOME_TYPE_TITLEBAR);
return 0;
}
@ -181,12 +181,9 @@ event_handle_configurerequest(void *data __attribute__ ((unused)),
{
client_t *c;
area_t geometry;
workspace_t *ws;
if((c = client_getbywin(ev->window)))
{
ws = workspace_client_get(c);
geometry = c->geometry;
if(ev->value_mask & XCB_CONFIG_WINDOW_X)
@ -201,11 +198,11 @@ event_handle_configurerequest(void *data __attribute__ ((unused)),
if(geometry.x != c->geometry.x || geometry.y != c->geometry.y
|| geometry.width != c->geometry.width || geometry.height != c->geometry.height)
{
if(c->isfloating || ws->layout == layout_floating)
if(c->isfloating || layout_get_current(c->screen) == layout_floating)
client_resize(c, geometry, false);
else
{
ws->need_arrange = true;
globalconf.screens[c->screen].need_arrange = true;
/* If we do not resize the client, at least tell it that it
* has its new configuration. That fixes at least
* gnome-terminal */
@ -466,7 +463,6 @@ event_handle_propertynotify(void *data __attribute__ ((unused)),
{
client_t *c;
xcb_window_t trans;
workspace_t *ws;
if(ev->state == XCB_PROPERTY_DELETE)
return 0; /* ignore */
@ -474,11 +470,10 @@ event_handle_propertynotify(void *data __attribute__ ((unused)),
{
if(ev->atom == WM_TRANSIENT_FOR)
{
ws = workspace_client_get(c);
xutil_get_transient_for_hint(connection, c->win, &trans);
if(!c->isfloating
&& (c->isfloating = (client_getbywin(trans) != NULL)))
ws->need_arrange = true;
globalconf.screens[c->screen].need_arrange = true;
}
else if (ev->atom == WM_NORMAL_HINTS)
client_updatesizehints(c);

46
ewmh.c
View File

@ -24,7 +24,7 @@
#include <xcb/xcb_aux.h>
#include "ewmh.h"
#include "workspace.h"
#include "tag.h"
#include "focus.h"
#include "screen.h"
#include "client.h"
@ -188,9 +188,9 @@ void
ewmh_update_net_numbers_of_desktop(int phys_screen)
{
uint32_t count = 0;
workspace_t *workspace;
tag_t *tag;
for(workspace = globalconf.workspaces; workspace; workspace = workspace->next)
for(tag = globalconf.screens[phys_screen].tags; tag; tag = tag->next)
count++;
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
@ -202,14 +202,16 @@ void
ewmh_update_net_current_desktop(int phys_screen)
{
uint32_t count = 0;
workspace_t *workspace;
tag_t *tag, **curtags = tags_get_current(phys_screen);
for(workspace = globalconf.workspaces; workspace; workspace = workspace->next)
for(tag = globalconf.screens[phys_screen].tags; tag != curtags[0]; tag = tag->next)
count++;
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
xcb_aux_get_screen(globalconf.connection, phys_screen)->root,
net_current_desktop, CARDINAL, 32, 1, &count);
p_delete(&curtags);
}
void
@ -217,14 +219,14 @@ ewmh_update_net_desktop_names(int phys_screen)
{
char buf[1024], *pos;
ssize_t len, curr_size;
workspace_t *workspace;
tag_t *tag;
pos = buf;
len = 0;
for(workspace = globalconf.workspaces; workspace; workspace = workspace->next)
for(tag = globalconf.screens[phys_screen].tags; tag; tag = tag->next)
{
curr_size = a_strlen(workspace->name);
a_strcpy(pos, sizeof(buf), workspace->name);
curr_size = a_strlen(tag->name);
a_strcpy(pos, sizeof(buf), tag->name);
pos += curr_size + 1;
len += curr_size + 1;
}
@ -238,7 +240,7 @@ void
ewmh_update_net_active_window(int phys_screen)
{
xcb_window_t win;
client_t *sel = focus_client_getcurrent(globalconf.screens[phys_screen].workspace);
client_t *sel = focus_get_current_client(phys_screen);
win = sel ? sel->win : XCB_NONE;
@ -251,11 +253,12 @@ static void
ewmh_process_state_atom(client_t *c, xcb_atom_t state, int set)
{
const uint32_t raise_window_val = XCB_STACK_MODE_ABOVE;
int screen;
if(state == net_wm_state_sticky)
{
/* \todo support for sticky */
tag_t *tag;
for(tag = globalconf.screens[c->screen].tags; tag; tag = tag->next)
tag_client(c, tag);
}
else if(state == net_wm_state_skip_taskbar)
{
@ -287,8 +290,7 @@ ewmh_process_state_atom(client_t *c, xcb_atom_t state, int set)
}
else if(set == _NET_WM_STATE_ADD)
{
screen = workspace_screen_get(workspace_client_get(c));
geometry = screen_area_get(screen, NULL, &globalconf.screens[screen].padding);
geometry = screen_area_get(c->screen, NULL, &globalconf.screens[c->screen].padding);
/* save geometry */
c->m_geometry = c->geometry;
c->wasfloating = c->isfloating;
@ -304,7 +306,7 @@ ewmh_process_state_atom(client_t *c, xcb_atom_t state, int set)
c->noborder = true;
client_setfloating(c, true, LAYER_FULLSCREEN);
}
widget_invalidate_cache(WIDGET_CACHE_CLIENTS);
widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
client_resize(c, geometry, false);
xcb_configure_window(globalconf.connection, c->win, XCB_CONFIG_WINDOW_STACK_MODE, &raise_window_val);
}
@ -365,21 +367,17 @@ ewmh_process_client_message(xcb_client_message_event_t *ev)
{
client_t *c;
int screen;
unsigned int i;
workspace_t *ws;
if(ev->type == net_current_desktop)
{
for(screen = 0;
screen < xcb_setup_roots_length(xcb_get_setup(globalconf.connection));
screen++)
{
if(ev->window == xcb_aux_get_screen(globalconf.connection, screen)->root)
{
for(i = 0, ws = globalconf.workspaces; i < ev->data.data32[0]; i++, ws = ws ->next);
globalconf.screens[screen].workspace = ws;
}
}
else if(ev->type == net_close_window)
tag_view_only_byindex(screen, ev->data.data32[0]);
}
if(ev->type == net_close_window)
{
if((c = client_getbywin(ev->window)))
client_kill(c);

25
focus.c
View File

@ -21,7 +21,7 @@
#include "focus.h"
#include "cnode.h"
#include "workspace.h"
#include "tag.h"
extern awesome_t globalconf;
@ -61,28 +61,33 @@ focus_client_delete(client_t *c)
}
static client_t *
focus_get_latest_client_for_workspace(workspace_t *ws, int nindex)
focus_get_latest_client_for_tags(tag_t **t, int nindex)
{
client_node_t *node;
tag_t **tags;
int i = 0;
for(node = globalconf.focus; node; node = node->next)
if(node->client && !node->client->skip && !node->client->ishidden)
if(workspace_client_get(node->client) == ws)
if(i-- == nindex)
return node->client;
for(tags = t; *tags; tags++)
if(is_client_tagged(node->client, *tags))
if(i-- == nindex)
return node->client;
return NULL;
}
/** Get the latest focused client on a workspace.
* \param ws The workspace.
/** Get the latest focused client on a screen.
* \param screen The virtual screen number.
* \return A pointer to an existing client.
*/
client_t *
focus_client_getcurrent(workspace_t *ws)
focus_get_current_client(int screen)
{
return focus_get_latest_client_for_workspace(ws, 0);
tag_t **curtags = tags_get_current(screen);
client_t *sel = focus_get_latest_client_for_tags(curtags, 0);
p_delete(&curtags);
return sel;
}
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -27,7 +27,7 @@
void focus_client_push(client_t *);
void focus_client_append(client_t *);
void focus_client_delete(client_t *);
client_t * focus_client_getcurrent(workspace_t *);
client_t * focus_get_current_client(int);
#endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -23,12 +23,13 @@
#include <xcb/xcb_atom.h>
#include <xcb/xcb_aux.h>
#include "tag.h"
#include "focus.h"
#include "widget.h"
#include "window.h"
#include "client.h"
#include "screen.h"
#include "workspace.h"
#include "layouts/magnifier.h"
#include "layouts/tile.h"
#include "layouts/max.h"
#include "layouts/fibonacci.h"
@ -36,27 +37,26 @@
extern awesome_t globalconf;
/** Arrange windows following current selected layout.
* \param ws The workspace to arrange.
/** Arrange windows following current selected layout
* \param screen the screen to arrange
*/
static void
arrange(workspace_t *ws)
arrange(int screen)
{
client_t *c;
int fscreen, screen = workspace_screen_get(ws), phys_screen = screen_virttophys(screen);
layout_t *curlay = layout_get_current(screen);
int fscreen, phys_screen = screen_virttophys(screen);
xcb_query_pointer_cookie_t qp_c;
xcb_query_pointer_reply_t *qp_r;
workspace_t *cws;
for(c = globalconf.clients; c; c = c->next)
if((cws = workspace_client_get(c)) == ws && !c->ishidden)
{
screen_client_moveto(c, screen);
{
if(!c->ishidden && client_isvisible(c, screen))
client_unban(c);
}
/* we don't touch other screens windows */
else if(c->ishidden || workspace_screen_get(cws) == -1)
else if(c->screen == screen)
client_ban(c);
}
qp_c = xcb_query_pointer_unchecked(globalconf.connection,
xcb_aux_get_screen(globalconf.connection,
@ -81,25 +81,26 @@ arrange(workspace_t *ws)
/* if the mouse in on the same screen we just rearranged, and no
* client are currently focused, pick the first one in history */
if(fscreen == screen
&& (c = focus_client_getcurrent(ws)))
client_focus(c);
&& (c = focus_get_current_client(screen)))
client_focus(c, screen);
}
p_delete(&qp_r);
}
if(ws->layout)
ws->layout(ws);
if(curlay)
curlay(screen);
/* reset status */
ws->need_arrange = false;
globalconf.screens[screen].need_arrange = false;
/* call hook */
luaA_workspace_userdata_new(ws);
lua_pushnumber(globalconf.L, screen + 1);
luaA_dofunction(globalconf.L, globalconf.hooks.arrange, 1);
}
/** Refresh the screens disposition.
/** Refresh the screen disposition
* \return true if the screen was arranged, false otherwise
*/
void
layout_refresh(void)
@ -107,8 +108,25 @@ layout_refresh(void)
int screen;
for(screen = 0; screen < globalconf.screens_info->nscreen; screen++)
if(globalconf.screens[screen].workspace && globalconf.screens[screen].workspace->need_arrange)
arrange(globalconf.screens[screen].workspace);
if(globalconf.screens[screen].need_arrange)
arrange(screen);
}
/** Get current layout used on screen.
* \param screen Virtual screen number.
* \return layout used on that screen
*/
layout_t *
layout_get_current(int screen)
{
layout_t *l = NULL;
tag_t **curtags = tags_get_current(screen);
if(curtags[0])
l = curtags[0]->layout;
p_delete(&curtags);
return l;
}
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -25,6 +25,9 @@
#include "common/list.h"
#include "common/util.h"
typedef void (layout_t)(int);
layout_t * layout_get_current(int);
void layout_refresh(void);
#endif

View File

@ -20,19 +20,18 @@
*/
#include "screen.h"
#include "workspace.h"
#include "tag.h"
#include "client.h"
#include "layouts/fibonacci.h"
extern awesome_t globalconf;
static void
layout_fibonacci(workspace_t *ws, int shape)
layout_fibonacci(int screen, int shape)
{
int n = 0, i = 0;
client_t *c;
area_t geometry, area;
int screen = workspace_screen_get(ws);
geometry = area = screen_area_get(screen,
globalconf.screens[screen].statusbar,
&globalconf.screens[screen].padding);
@ -89,15 +88,15 @@ layout_fibonacci(workspace_t *ws, int shape)
}
void
layout_spiral(workspace_t *ws)
layout_spiral(int screen)
{
layout_fibonacci(ws, 0);
layout_fibonacci(screen, 0);
}
void
layout_dwindle(workspace_t *ws)
layout_dwindle(int screen)
{
layout_fibonacci(ws, 1);
layout_fibonacci(screen, 1);
}
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -20,16 +20,15 @@
*/
#include "client.h"
#include "workspace.h"
#include "tag.h"
#include "layouts/floating.h"
extern awesome_t globalconf;
void
layout_floating(workspace_t *ws)
layout_floating(int screen)
{
client_t *c;
int screen = workspace_screen_get(ws);
for(c = globalconf.clients; c; c = c->next)
if(client_isvisible(c, screen) && !c->ismax)

View File

@ -20,7 +20,7 @@
*/
#include "client.h"
#include "workspace.h"
#include "tag.h"
#include "screen.h"
#include "focus.h"
#include "layouts/magnifier.h"
@ -28,16 +28,16 @@
extern awesome_t globalconf;
void
layout_magnifier(workspace_t *ws)
layout_magnifier(int screen)
{
int n = 0;
client_t *c, *focus;
int screen = workspace_screen_get(ws);
tag_t **curtags = tags_get_current(screen);
area_t geometry, area = screen_area_get(screen,
globalconf.screens[screen].statusbar,
&globalconf.screens[screen].padding);
focus = focus_client_getcurrent(ws);
focus = focus_get_current_client(screen);
/* If focused window is not tiled, take the first one which is tiled. */
if(!IS_TILED(focus, screen))
@ -45,10 +45,10 @@ layout_magnifier(workspace_t *ws)
/* No windows is tiled, nothing to do. */
if(!focus)
return;
goto bailout;
geometry.width = area.width * ws->mwfact;
geometry.height = area.height * ws->mwfact;
geometry.width = area.width * curtags[0]->mwfact;
geometry.height = area.height * curtags[0]->mwfact;
geometry.x = area.x + (area.width - geometry.width) / 2;
geometry.y = area.y + (area.height - geometry.height) / 2;
client_resize(focus, geometry, globalconf.resize_hints);
@ -62,7 +62,7 @@ layout_magnifier(workspace_t *ws)
/* No other clients. */
if(!n)
return;
goto bailout;
geometry.x = area.x;
geometry.y = area.y;
@ -81,5 +81,8 @@ layout_magnifier(workspace_t *ws)
geometry.width += 2 * c->border;
geometry.y += geometry.height;
}
bailout:
p_delete(&curtags);
}
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -19,7 +19,7 @@
*
*/
#include "workspace.h"
#include "tag.h"
#include "screen.h"
#include "client.h"
#include "focus.h"
@ -28,13 +28,12 @@
extern awesome_t globalconf;
void
layout_max(workspace_t *ws)
layout_max(int screen)
{
client_t *c, *focus;
int screen = workspace_screen_get(ws);
area_t area = screen_area_get(screen,
globalconf.screens[screen].statusbar,
&globalconf.screens[screen].padding);
globalconf.screens[screen].statusbar,
&globalconf.screens[screen].padding);
for(c = globalconf.clients; c; c = c->next)
if(IS_TILED(c, screen))
@ -46,7 +45,7 @@ layout_max(workspace_t *ws)
area.height += 2 * c->border;
}
if((focus = focus_client_getcurrent(ws))
if((focus = focus_get_current_client(screen))
&& IS_TILED(focus, screen))
client_raise(focus);
}

View File

@ -22,7 +22,7 @@
#include <stdio.h>
#include "screen.h"
#include "workspace.h"
#include "tag.h"
#include "client.h"
#include "layouts/tile.h"
#include "common/util.h"
@ -30,18 +30,17 @@
extern awesome_t globalconf;
static void
_tile(workspace_t *ws, const position_t position)
_tile(int screen, const position_t position)
{
/* windows area geometry */
int wah = 0, waw = 0, wax = 0, way = 0;
/* master size */
unsigned int mw = 0, mh = 0;
int n, i, masterwin = 0, otherwin = 0;
int screen, real_ncol = 1, win_by_col = 1, current_col = 0;
int real_ncol = 1, win_by_col = 1, current_col = 0;
area_t area, geometry = { 0, 0, 0, 0, NULL, NULL };
client_t *c;
screen = workspace_screen_get(ws);
tag_t **curtags = tags_get_current(screen);
area = screen_area_get(screen,
globalconf.screens[screen].statusbar,
@ -56,34 +55,34 @@ _tile(workspace_t *ws, const position_t position)
wax = area.x;
way = area.y;
masterwin = MIN(n, ws->nmaster);
masterwin = MIN(n, curtags[0]->nmaster);
otherwin = MAX(n - masterwin, 0);
if(ws->nmaster)
if(curtags[0]->nmaster)
switch(position)
{
case Right:
case Left:
mh = masterwin ? wah / masterwin : wah;
mw = otherwin ? waw * ws->mwfact : waw;
mw = otherwin ? waw * curtags[0]->mwfact : waw;
break;
default:
mh = otherwin ? wah * ws->mwfact : wah;
mh = otherwin ? wah * curtags[0]->mwfact : wah;
mw = masterwin ? waw / masterwin : waw;
break;
}
else
mh = mw = 0;
real_ncol = ws->ncol > 0 ? MIN(otherwin, ws->ncol) : MIN(otherwin, 1);
real_ncol = curtags[0]->ncol > 0 ? MIN(otherwin, curtags[0]->ncol) : MIN(otherwin, 1);
for(i = 0, c = globalconf.clients; c; c = c->next)
{
if(!IS_TILED(c, screen))
continue;
if(i < ws->nmaster)
if(i < curtags[0]->nmaster)
{
switch(position)
{
@ -117,8 +116,8 @@ _tile(workspace_t *ws, const position_t position)
if(real_ncol)
win_by_col = otherwin / real_ncol;
if((i - ws->nmaster)
&& (i - ws->nmaster) % win_by_col == 0
if((i - curtags[0]->nmaster)
&& (i - curtags[0]->nmaster) % win_by_col == 0
&& current_col < real_ncol - 1)
current_col++;
@ -134,10 +133,10 @@ _tile(workspace_t *ws, const position_t position)
geometry.width = (waw - mw) / real_ncol - 2 * c->border;
if(i == ws->nmaster || otherwin <= real_ncol || (i - ws->nmaster) % win_by_col == 0)
if(i == curtags[0]->nmaster || otherwin <= real_ncol || (i - curtags[0]->nmaster) % win_by_col == 0)
geometry.y = way;
else
geometry.y = way + ((i - ws->nmaster) % win_by_col) * (geometry.height + 2 * c->border);
geometry.y = way + ((i - curtags[0]->nmaster) % win_by_col) * (geometry.height + 2 * c->border);
geometry.x = wax + current_col * (geometry.width + 2 * c->border);
@ -153,10 +152,10 @@ _tile(workspace_t *ws, const position_t position)
geometry.height = (wah - mh) / real_ncol - 2 * c->border;
if(i == ws->nmaster || otherwin <= real_ncol || (i - ws->nmaster) % win_by_col == 0)
if(i == curtags[0]->nmaster || otherwin <= real_ncol || (i - curtags[0]->nmaster) % win_by_col == 0)
geometry.x = wax;
else
geometry.x = wax + ((i - ws->nmaster) % win_by_col) * (geometry.width + 2 * c->border);
geometry.x = wax + ((i - curtags[0]->nmaster) % win_by_col) * (geometry.width + 2 * c->border);
geometry.y = way + current_col * (geometry.height + 2 * c->border);
@ -167,30 +166,32 @@ _tile(workspace_t *ws, const position_t position)
}
i++;
}
p_delete(&curtags);
}
void
layout_tile(workspace_t *ws)
layout_tile(int screen)
{
_tile(ws, Right);
_tile(screen, Right);
}
void
layout_tileleft(workspace_t *ws)
layout_tileleft(int screen)
{
_tile(ws, Left);
_tile(screen, Left);
}
void
layout_tilebottom(workspace_t *ws)
layout_tilebottom(int screen)
{
_tile(ws, Bottom);
_tile(screen, Bottom);
}
void
layout_tiletop(workspace_t *ws)
layout_tiletop(int screen)
{
_tile(ws, Top);
_tile(screen, Top);
}
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

30
lua.c
View File

@ -32,7 +32,7 @@
#include "config.h"
#include "structs.h"
#include "lua.h"
#include "workspace.h"
#include "tag.h"
#include "client.h"
#include "window.h"
#include "statusbar.h"
@ -49,8 +49,8 @@ extern const struct luaL_reg awesome_client_methods[];
extern const struct luaL_reg awesome_client_meta[];
extern const struct luaL_reg awesome_titlebar_methods[];
extern const struct luaL_reg awesome_titlebar_meta[];
extern const struct luaL_reg awesome_workspace_methods[];
extern const struct luaL_reg awesome_workspace_meta[];
extern const struct luaL_reg awesome_tag_methods[];
extern const struct luaL_reg awesome_tag_meta[];
extern const struct luaL_reg awesome_widget_methods[];
extern const struct luaL_reg awesome_widget_meta[];
extern const struct luaL_reg awesome_statusbar_methods[];
@ -191,17 +191,16 @@ luaA_screen_count(lua_State *L)
return 1;
}
/** Get the workspace displayed on a screen.
* \param A screen number.
*/
/** Give the focus to a screen.
* \param A screen number
*/
static int
luaA_screen_workspace_get(lua_State *L)
luaA_screen_focus(lua_State *L)
{
/* Our table begin at 0, Lua begins at 1 */
int screen = luaL_checknumber(L, 1) - 1;
luaA_checkscreen(screen);
if(globalconf.screens[screen].workspace)
return luaA_workspace_userdata_new(globalconf.screens[screen].workspace);
client_focus(NULL, screen);
return 0;
}
@ -427,7 +426,7 @@ luaA_init(void)
{
{ "coords_get", luaA_screen_coords_get },
{ "count", luaA_screen_count },
{ "workspace_get", luaA_screen_workspace_get },
{ "focus", luaA_screen_focus },
{ NULL, NULL }
};
static const struct luaL_reg awesome_hooks_lib[] =
@ -459,8 +458,8 @@ luaA_init(void)
/* Export hooks lib */
luaL_register(L, "mouse", awesome_mouse_lib);
/* Export workspace */
luaA_openlib(L, "workspace", awesome_workspace_methods, awesome_workspace_meta);
/* Export tag */
luaA_openlib(L, "tag", awesome_tag_methods, awesome_tag_meta);
/* Export statusbar */
luaA_openlib(L, "statusbar", awesome_statusbar_methods, awesome_statusbar_meta);
@ -492,13 +491,18 @@ luaA_init(void)
bool
luaA_parserc(const char* rcfile)
{
int screen;
if(luaL_dofile(globalconf.L, rcfile))
{
fprintf(stderr, "%s\n", lua_tostring(globalconf.L, -1));
return false;
}
/* \todo Assure there's at least one workspace */
/* Assure there's at least one tag */
for(screen = 0; screen < globalconf.screens_info->nscreen; screen++)
if(!globalconf.screens[screen].tags)
tag_append_to_screen(tag_new("default", layout_tile, 0.5, 1, 0), screen);
return true;
}

133
mouse.c
View File

@ -27,7 +27,7 @@
#include "mouse.h"
#include "screen.h"
#include "workspace.h"
#include "tag.h"
#include "event.h"
#include "client.h"
#include "titlebar.h"
@ -126,12 +126,11 @@ static area_t
mouse_snapclient(client_t *c, area_t geometry, int snap)
{
client_t *snapper;
int screen = workspace_screen_get(workspace_client_get(c));
area_t snapper_geometry;
area_t screen_geometry =
screen_area_get(screen,
globalconf.screens[screen].statusbar,
&globalconf.screens[screen].padding);
screen_area_get(c->screen,
globalconf.screens[c->screen].statusbar,
&globalconf.screens[c->screen].padding);
geometry = titlebar_geometry_add(c->titlebar, geometry);
geometry.width += 2 * c->border;
@ -141,7 +140,7 @@ mouse_snapclient(client_t *c, area_t geometry, int snap)
mouse_snapclienttogeometry_inside(geometry, screen_geometry, snap);
for(snapper = globalconf.clients; snapper; snapper = snapper->next)
if(snapper != c && client_isvisible(c, screen))
if(snapper != c && client_isvisible(c, c->screen))
{
snapper_geometry = snapper->geometry;
snapper_geometry.width += 2 * c->border;
@ -297,9 +296,10 @@ mouse_warp_pointer(xcb_window_t window, int x, int y)
static void
mouse_client_move(client_t *c, int snap)
{
int ocx, ocy, newscreen;
area_t geometry;
client_t *target;
workspace_t *ws = workspace_client_get(c);
layout_t *layout;
simple_window_t *sw = NULL;
draw_context_t *ctx;
xcb_generic_event_t *ev = NULL;
@ -309,8 +309,8 @@ mouse_client_move(client_t *c, int snap)
xcb_query_pointer_reply_t *query_pointer_r = NULL, *mquery_pointer_r = NULL;
xcb_query_pointer_cookie_t query_pointer_c;
xcb_screen_t *s;
int ocx, ocy, newscreen, screen = workspace_screen_get(ws);
layout = layout_get_current(c->screen);
s = xcb_aux_get_screen(globalconf.connection, c->phys_screen);
/* Send pointer requests */
@ -334,16 +334,18 @@ mouse_client_move(client_t *c, int snap)
query_pointer_r = xcb_query_pointer_reply(globalconf.connection, query_pointer_c, NULL);
if(c->isfloating || ws->layout == layout_floating)
if(c->isfloating || layout == layout_floating)
{
sw = mouse_resizebar_new(c->phys_screen, c->border, c->geometry, &ctx);
xcb_aux_sync(globalconf.connection);
}
while(true)
{
/* XMaskEvent allows to retrieve only specified events from
* the queue and requeue the other events... */
while(ev || (ev = xcb_wait_for_event(globalconf.connection)))
{
switch((ev->response_type & 0x7f))
{
case XCB_BUTTON_RELEASE:
@ -357,7 +359,7 @@ mouse_client_move(client_t *c, int snap)
p_delete(&ev);
return;
case XCB_MOTION_NOTIFY:
if(c->isfloating || ws->layout == layout_floating)
if(c->isfloating || layout == layout_floating)
{
ev_motion = (xcb_motion_notify_event_t *) ev;
@ -365,21 +367,6 @@ mouse_client_move(client_t *c, int snap)
geometry.y = ocy + (ev_motion->event_y - query_pointer_r->root_y);
geometry = mouse_snapclient(c, geometry, snap);
if((newscreen = screen_get_bycoord(globalconf.screens_info, screen,
geometry.x, geometry.y)) != screen)
{
if((ws = globalconf.screens[newscreen].workspace))
{
screen = workspace_screen_get(ws);
workspace_client_set(c, ws);
}
else
{
p_delete(&ev);
break;
}
}
c->ismoving = true;
client_resize(c, geometry, false);
c->ismoving = false;
@ -393,24 +380,20 @@ mouse_client_move(client_t *c, int snap)
{
query_pointer_c = xcb_query_pointer_unchecked(globalconf.connection, s->root);
mquery_pointer_r = xcb_query_pointer_reply(globalconf.connection, query_pointer_c, NULL);
if((newscreen = screen_get_bycoord(globalconf.screens_info,
screen,
if((newscreen = screen_get_bycoord(globalconf.screens_info, c->screen,
mquery_pointer_r->root_x,
mquery_pointer_r->root_y)) != screen
&& globalconf.screens[newscreen].workspace)
mquery_pointer_r->root_y)) != c->screen)
{
ws->need_arrange = true;
ws = globalconf.screens[newscreen].workspace;
screen = workspace_screen_get(ws);
workspace_client_set(c, ws);
ws->need_arrange = true;
screen_client_moveto(c, newscreen, true);
globalconf.screens[c->screen].need_arrange = true;
globalconf.screens[newscreen].need_arrange = true;
layout_refresh();
}
if((target = client_getbywin(mquery_pointer_r->child))
&& target != c && !target->isfloating)
{
client_list_swap(&globalconf.clients, c, target);
ws->need_arrange = true;
globalconf.screens[c->screen].need_arrange = true;
layout_refresh();
}
p_delete(&mquery_pointer_r);
@ -425,6 +408,8 @@ mouse_client_move(client_t *c, int snap)
p_delete(&ev);
break;
}
}
}
}
@ -592,57 +577,62 @@ mouse_client_resize_floating(client_t *c, corner_t corner)
}
/** Resize the master column/row of a tiled layout
* \param c A client on the workspace/layout to resize.
* \param c A client on the tag/layout to resize.
*/
static void
mouse_client_resize_tiled(client_t *c)
{
xcb_screen_t *xscreen;
xcb_screen_t *screen;
/* screen area modulo statusbar */
area_t area;
/* current workspace */
workspace_t *ws = workspace_client_get(c);
int mouse_x, mouse_y, screen = workspace_screen_get(ws);
/* current tag */
tag_t *tag;
/* current layout */
layout_t *layout;
int mouse_x, mouse_y;
size_t cursor = CurResize;
xscreen = xcb_aux_get_screen(globalconf.connection, c->phys_screen);
screen = xcb_aux_get_screen(globalconf.connection, c->phys_screen);
tag = tags_get_current(c->screen)[0];
layout = tag->layout;
area = screen_area_get(screen,
globalconf.screens[screen].statusbar,
&globalconf.screens[screen].padding);
area = screen_area_get(tag->screen,
globalconf.screens[tag->screen].statusbar,
&globalconf.screens[tag->screen].padding);
mouse_query_pointer(xscreen->root, &mouse_x, &mouse_y);
mouse_query_pointer(screen->root, &mouse_x, &mouse_y);
/* select initial pointer position */
if(ws->layout == layout_tile)
if(layout == layout_tile)
{
mouse_x = area.x + area.width * ws->mwfact;
mouse_x = area.x + area.width * tag->mwfact;
cursor = CurResizeH;
}
else if(ws->layout == layout_tileleft)
else if(layout == layout_tileleft)
{
mouse_x = area.x + area.width * (1. - ws->mwfact);
mouse_x = area.x + area.width * (1. - tag->mwfact);
cursor = CurResizeH;
}
else if(ws->layout == layout_tilebottom)
else if(layout == layout_tilebottom)
{
mouse_y = area.y + area.height * ws->mwfact;
mouse_y = area.y + area.height * tag->mwfact;
cursor = CurResizeV;
}
else if(ws->layout == layout_tiletop)
else if(layout == layout_tiletop)
{
mouse_y = area.y + area.height * (1. - ws->mwfact);
mouse_y = area.y + area.height * (1. - tag->mwfact);
cursor = CurResizeV;
}
else
return;
/* grab the pointer */
if(!mouse_grab_pointer(xscreen->root, cursor))
if(!mouse_grab_pointer(screen->root, cursor))
return;
/* set pointer to the moveable border */
mouse_warp_pointer(xscreen->root, mouse_x, mouse_y);
mouse_warp_pointer(screen->root, mouse_x, mouse_y);
xcb_aux_sync(globalconf.connection);
@ -655,20 +645,20 @@ mouse_client_resize_tiled(client_t *c)
fact_x = (double) (mouse_x - area.x) / area.width;
fact_y = (double) (mouse_y - area.y) / area.height;
if(ws->layout == layout_tile)
if(layout == layout_tile)
mwfact = fact_x;
else if(ws->layout == layout_tileleft)
else if(layout == layout_tileleft)
mwfact = 1. - fact_x;
else if(ws->layout == layout_tilebottom)
else if(layout == layout_tilebottom)
mwfact = fact_y;
else if(ws->layout == layout_tiletop)
else if(layout == layout_tiletop)
mwfact = 1. - fact_y;
/* refresh layout */
if(fabs(ws->mwfact - mwfact) >= 0.01)
if(fabs(tag->mwfact - mwfact) >= 0.01)
{
ws->mwfact = mwfact;
ws->need_arrange = true;
tag->mwfact = mwfact;
globalconf.screens[tag->screen].need_arrange = true;
layout_refresh();
xcb_aux_sync(globalconf.connection);
}
@ -689,13 +679,16 @@ static void
mouse_client_resize(client_t *c, corner_t corner)
{
int n, screen;
workspace_t *ws = workspace_client_get(c);
tag_t **curtags;
layout_t *layout;
xcb_screen_t *s;
curtags = tags_get_current(c->screen);
layout = curtags[0]->layout;
s = xcb_aux_get_screen(globalconf.connection, c->phys_screen);
/* only handle floating and tiled layouts */
if(ws->layout == layout_floating || c->isfloating)
if(layout == layout_floating || c->isfloating)
{
if(c->isfixed)
return;
@ -704,16 +697,16 @@ mouse_client_resize(client_t *c, corner_t corner)
mouse_client_resize_floating(c, corner);
}
else if (ws->layout == layout_tile || ws->layout == layout_tileleft
|| ws->layout == layout_tilebottom || ws->layout == layout_tiletop)
else if (layout == layout_tile || layout == layout_tileleft
|| layout == layout_tilebottom || layout == layout_tiletop)
{
screen = workspace_screen_get(ws);
screen = c->screen;
for(n = 0, c = globalconf.clients; c; c = c->next)
if(IS_TILED(c, screen))
n++;
/* only masters on this screen? */
if(n <= ws->nmaster) return;
if(n <= curtags[0]->nmaster) return;
/* no tiled clients on this screen? */
for(c = globalconf.clients; c && !IS_TILED(c, screen); c = c->next);
@ -786,8 +779,8 @@ static int
luaA_mouse_screen_get(lua_State *L)
{
int screen;
xcb_query_pointer_cookie_t qc;
xcb_query_pointer_reply_t *qr;
xcb_query_pointer_cookie_t qc;
xcb_query_pointer_reply_t *qr;
qc = xcb_query_pointer(globalconf.connection,
xcb_aux_get_screen(globalconf.connection,

View File

@ -26,7 +26,6 @@
#include "screen.h"
#include "client.h"
#include "titlebar.h"
#include "workspace.h"
#include "layouts/floating.h"
extern awesome_t globalconf;
@ -72,21 +71,21 @@ placement_smart(client_t *c)
area_t newgeometry = { 0, 0, 0, 0, NULL, NULL };
area_t *screen_geometry, *arealist = NULL, *r;
bool found = false;
workspace_t *ws = workspace_client_get(c);
int screen = workspace_screen_get(ws);
layout_t *layout;
screen_geometry = p_new(area_t, 1);
*screen_geometry = screen_area_get(screen,
globalconf.screens[screen].statusbar,
&globalconf.screens[screen].padding);
*screen_geometry = screen_area_get(c->screen,
globalconf.screens[c->screen].statusbar,
&globalconf.screens[c->screen].padding);
layout = layout_get_current(c->screen);
area_list_push(&arealist, screen_geometry);
for(client = globalconf.clients; client; client = client->next)
if((client->isfloating || ws->layout == layout_floating)
&& client_isvisible(client, screen))
if((client->isfloating || layout == layout_floating)
&& client_isvisible(client, c->screen))
{
newgeometry = client->f_geometry;
newgeometry.width += 2 * client->border;
@ -120,7 +119,7 @@ placement_smart(client_t *c)
newgeometry.height = c->f_geometry.height;
newgeometry = titlebar_geometry_add(c->titlebar, newgeometry);
newgeometry = placement_fix_offscreen(newgeometry, screen, c->border);
newgeometry = placement_fix_offscreen(newgeometry, c->screen, c->border);
newgeometry = titlebar_geometry_remove(c->titlebar, newgeometry);
area_list_wipe(&arealist);
@ -134,7 +133,6 @@ placement_under_mouse(client_t *c)
xcb_query_pointer_cookie_t qp_c;
xcb_query_pointer_reply_t *qp_r;
area_t finalgeometry = c->f_geometry;
int screen = workspace_screen_get(workspace_client_get(c));
qp_c = xcb_query_pointer(globalconf.connection,
xcb_aux_get_screen(globalconf.connection, c->phys_screen)->root);
@ -147,7 +145,7 @@ placement_under_mouse(client_t *c)
}
finalgeometry = titlebar_geometry_add(c->titlebar, finalgeometry);
finalgeometry = placement_fix_offscreen(finalgeometry, screen, c->border);
finalgeometry = placement_fix_offscreen(finalgeometry, c->screen, c->border);
finalgeometry = titlebar_geometry_remove(c->titlebar, finalgeometry);
return finalgeometry;

131
screen.c
View File

@ -25,9 +25,9 @@
#include <xcb/xcb_aux.h>
#include "screen.h"
#include "tag.h"
#include "focus.h"
#include "client.h"
#include "workspace.h"
#include "layouts/floating.h"
extern awesome_t globalconf;
@ -121,80 +121,93 @@ screen_virttophys(int screen)
/** Move a client to a virtual screen.
* \param c The client to move.
* \param new_screen The new screen.
* \param new_screen The destinatiuon screen number.
* \param doresize Set to true if we also move the client to the new x and
* y of the new screen.
*/
void
screen_client_moveto(client_t *c, int new_screen)
screen_client_moveto(client_t *c, int new_screen, bool doresize)
{
area_t from, to, new_geometry, new_f_geometry;
int old_screen;
tag_t *tag;
int old_screen = c->screen;
area_t from, to;
old_screen = screen_get_bycoord(globalconf.screens_info, c->phys_screen,
c->geometry.x, c->geometry.y);
for(tag = globalconf.screens[old_screen].tags; tag; tag = tag->next)
untag_client(c, tag);
/* nothing to do */
if(old_screen == new_screen)
return;
c->screen = new_screen;
new_f_geometry = c->f_geometry;
/* tag client with new screen tags */
tag_client_with_current_selected(c);
from = screen_area_get(old_screen, NULL, NULL);
to = screen_area_get(new_screen, NULL, NULL);
/* compute new coords in new screen */
new_f_geometry.x = (c->f_geometry.x - from.x) + to.x;
new_f_geometry.y = (c->f_geometry.y - from.y) + to.y;
/* check that new coords are still in the screen */
if(new_f_geometry.width > to.width)
new_f_geometry.width = to.width;
if(new_f_geometry.height > to.height)
new_f_geometry.height = to.height;
if(new_f_geometry.x + new_f_geometry.width >= to.x + to.width)
new_f_geometry.x = to.x + to.width - new_f_geometry.width - 2 * c->border;
if(new_f_geometry.y + new_f_geometry.height >= to.y + to.height)
new_f_geometry.y = to.y + to.height - new_f_geometry.height - 2 * c->border;
if(c->ismax)
/* resize the windows if it's floating */
if(doresize && old_screen != c->screen)
{
new_geometry = c->geometry;
area_t new_geometry, new_f_geometry;
new_f_geometry = c->f_geometry;
to = screen_area_get(c->screen, NULL, NULL);
from = screen_area_get(old_screen, NULL, NULL);
/* compute new coords in new screen */
new_geometry.x = (c->geometry.x - from.x) + to.x;
new_geometry.y = (c->geometry.y - from.y) + to.y;
new_f_geometry.x = (c->f_geometry.x - from.x) + to.x;
new_f_geometry.y = (c->f_geometry.y - from.y) + to.y;
/* check that new coords are still in the screen */
if(new_geometry.width > to.width)
new_geometry.width = to.width;
if(new_geometry.height > to.height)
new_geometry.height = to.height;
if(new_geometry.x + new_geometry.width >= to.x + to.width)
new_geometry.x = to.x + to.width - new_geometry.width - 2 * c->border;
if(new_geometry.y + new_geometry.height >= to.y + to.height)
new_geometry.y = to.y + to.height - new_geometry.height - 2 * c->border;
if(new_f_geometry.width > to.width)
new_f_geometry.width = to.width;
if(new_f_geometry.height > to.height)
new_f_geometry.height = to.height;
if(new_f_geometry.x + new_f_geometry.width >= to.x + to.width)
new_f_geometry.x = to.x + to.width - new_f_geometry.width - 2 * c->border;
if(new_f_geometry.y + new_f_geometry.height >= to.y + to.height)
new_f_geometry.y = to.y + to.height - new_f_geometry.height - 2 * c->border;
/* compute new coords for max in new screen */
c->m_geometry.x = (c->m_geometry.x - from.x) + to.x;
c->m_geometry.y = (c->m_geometry.y - from.y) + to.y;
if(c->ismax)
{
new_geometry = c->geometry;
/* check that new coords are still in the screen */
if(c->m_geometry.width > to.width)
c->m_geometry.width = to.width;
if(c->m_geometry.height > to.height)
c->m_geometry.height = to.height;
if(c->m_geometry.x + c->m_geometry.width >= to.x + to.width)
c->m_geometry.x = to.x + to.width - c->m_geometry.width - 2 * c->border;
if(c->m_geometry.y + c->m_geometry.height >= to.y + to.height)
c->m_geometry.y = to.y + to.height - c->m_geometry.height - 2 * c->border;
/* compute new coords in new screen */
new_geometry.x = (c->geometry.x - from.x) + to.x;
new_geometry.y = (c->geometry.y - from.y) + to.y;
client_resize(c, new_geometry, false);
/* check that new coords are still in the screen */
if(new_geometry.width > to.width)
new_geometry.width = to.width;
if(new_geometry.height > to.height)
new_geometry.height = to.height;
if(new_geometry.x + new_geometry.width >= to.x + to.width)
new_geometry.x = to.x + to.width - new_geometry.width - 2 * c->border;
if(new_geometry.y + new_geometry.height >= to.y + to.height)
new_geometry.y = to.y + to.height - new_geometry.height - 2 * c->border;
/* compute new coords for max in new screen */
c->m_geometry.x = (c->m_geometry.x - from.x) + to.x;
c->m_geometry.y = (c->m_geometry.y - from.y) + to.y;
/* check that new coords are still in the screen */
if(c->m_geometry.width > to.width)
c->m_geometry.width = to.width;
if(c->m_geometry.height > to.height)
c->m_geometry.height = to.height;
if(c->m_geometry.x + c->m_geometry.width >= to.x + to.width)
c->m_geometry.x = to.x + to.width - c->m_geometry.width - 2 * c->border;
if(c->m_geometry.y + c->m_geometry.height >= to.y + to.height)
c->m_geometry.y = to.y + to.height - c->m_geometry.height - 2 * c->border;
client_resize(c, new_geometry, false);
}
/* if floating, move to this new coords */
else if(c->isfloating)
client_resize(c, new_f_geometry, false);
/* otherwise just register them */
else
{
c->f_geometry = new_f_geometry;
globalconf.screens[old_screen].need_arrange = true;
globalconf.screens[c->screen].need_arrange = true;
}
}
/* if floating, move to this new coords */
else if(c->isfloating)
client_resize(c, new_f_geometry, false);
/* otherwise just register them */
else
c->f_geometry = new_f_geometry;
}
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -27,7 +27,7 @@
area_t screen_area_get(int, statusbar_t *, padding_t *);
area_t display_area_get(int, statusbar_t *, padding_t *);
int screen_virttophys(int);
void screen_client_moveto(client_t *, int);
void screen_client_moveto(client_t *, int, bool);
#endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -24,6 +24,7 @@
#include "statusbar.h"
#include "screen.h"
#include "tag.h"
#include "widget.h"
#include "window.h"
@ -79,8 +80,7 @@ statusbar_position_update(statusbar_t *statusbar, position_t position)
xcb_screen_t *s = NULL;
bool ignore = false;
if(globalconf.screens[statusbar->screen].workspace)
globalconf.screens[statusbar->screen].workspace->need_arrange = true;
globalconf.screens[statusbar->screen].need_arrange = true;
simplewindow_delete(&statusbar->sw);
draw_context_delete(&statusbar->ctx);
@ -412,8 +412,7 @@ luaA_statusbar_remove(lua_State *L)
statusbar_position_update(*sb, Off);
statusbar_list_detach(&globalconf.screens[i].statusbar, *sb);
statusbar_unref(sb);
if(globalconf.screens[s->screen].workspace)
globalconf.screens[s->screen].workspace->need_arrange = true;
globalconf.screens[i].need_arrange = true;
return 0;
}

View File

@ -50,8 +50,6 @@ enum
CurTopLeft, CurTopRight, CurBotLeft, CurBotRight, CurLast
};
typedef struct workspace_t workspace_t;
typedef void (layout_t)(workspace_t *);
typedef struct button_t button_t;
typedef struct widget_t widget_t;
typedef struct widget_node_t widget_node_t;
@ -60,7 +58,8 @@ typedef struct client_t client_t;
typedef struct titlebar_t titlebar_t;
typedef struct keybinding_t keybinding_t;
typedef struct client_node_t client_node_t;
typedef struct workspace_client_node_t workspace_client_node_t;
typedef struct _tag_t tag_t;
typedef struct tag_client_node_t tag_client_node_t;
typedef area_t (FloatingPlacement)(client_t *);
typedef struct awesome_t awesome_t;
@ -280,6 +279,8 @@ struct client_t
bool skiptb;
/** Window of the client */
xcb_window_t win;
/** Client logical screen */
int screen;
/** Client physical screen */
int phys_screen;
/** Layer in the stacking order */
@ -300,14 +301,18 @@ struct client_node_t
client_node_t *prev, *next;
};
/** Workspace type */
struct workspace_t
/** Tag type */
struct _tag_t
{
/** Ref count */
int refcount;
/** Tag name */
char *name;
/** Current workspace layout */
/** Screen */
int screen;
/** true if selected */
bool selected;
/** Current tag layout */
layout_t *layout;
/** Master width factor */
double mwfact;
@ -315,19 +320,17 @@ struct workspace_t
int nmaster;
/** Number of columns in tile layout */
int ncol;
/** True if we need to arrange() */
bool need_arrange;
/** Next and previous workspaces */
workspace_t *prev, *next;
/** Next and previous tags */
tag_t *prev, *next;
};
/** Tag client link type */
struct workspace_client_node_t
struct tag_client_node_t
{
workspace_t *workspace;
tag_t *tag;
client_t *client;
/** Next and previous workspace_client_nodes */
workspace_client_node_t *prev, *next;
/** Next and previous tag_client_nodes */
tag_client_node_t *prev, *next;
};
/** Padding type */
@ -343,15 +346,16 @@ typedef struct
int right;
} padding_t;
/** An awesome screen. */
typedef struct
{
/** true if we need to arrange() */
bool need_arrange;
/** Tag list */
tag_t *tags;
/** Status bar */
statusbar_t *statusbar;
/** Padding */
padding_t padding;
/** Visible workspace */
workspace_t *workspace;
} screen_t;
/** Main configuration structure */
@ -400,8 +404,8 @@ struct awesome_t
client_node_t *focus;
/** Stack client history */
client_node_t *stack;
/** Link between workspaces and clients */
workspace_client_node_t *wclink;
/** Link between tags and clients */
tag_client_node_t *tclink;
/** Command line passed to awesome */
char *argv;
/** Last XMotionEvent coords */
@ -440,8 +444,6 @@ struct awesome_t
} hooks;
/** The timeout after which we need to stop select() */
struct timeval timer;
/** Workspace list */
workspace_t *workspaces;
};
#endif

564
tag.c Normal file
View File

@ -0,0 +1,564 @@
/*
* tag.c - tag management
*
* Copyright © 2007-2008 Julien Danjou <julien@danjou.info>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include <stdio.h>
#include <X11/Xutil.h>
#include "screen.h"
#include "tag.h"
#include "client.h"
#include "ewmh.h"
#include "widget.h"
#include "layouts/magnifier.h"
#include "layouts/tile.h"
#include "layouts/max.h"
#include "layouts/floating.h"
#include "layouts/fibonacci.h"
#include "layoutgen.h"
extern awesome_t globalconf;
/** View or unview a tag.
* \param tag the tag
* \param view set visible or not
*/
static void
tag_view(tag_t *tag, bool view)
{
tag->selected = view;
ewmh_update_net_current_desktop(screen_virttophys(tag->screen));
widget_invalidate_cache(tag->screen, WIDGET_CACHE_TAGS);
globalconf.screens[tag->screen].need_arrange = true;
}
/** Create a new tag. Parameteres values are checked.
* \param name tag name
* \param layout layout to use
* \param mwfact master width factor
* \param nmaster number of master windows
* \param ncol number of columns for slaves windows
* \return a new tag with all these parameters
*/
tag_t *
tag_new(const char *name, layout_t *layout, double mwfact, int nmaster, int ncol)
{
tag_t *tag;
tag = p_new(tag_t, 1);
tag->name = a_strdup(name);
tag->layout = layout;
tag->mwfact = mwfact;
if(tag->mwfact <= 0 || tag->mwfact >= 1)
tag->mwfact = 0.5;
if((tag->nmaster = nmaster) < 0)
tag->nmaster = 1;
if((tag->ncol = ncol) < 1)
tag->ncol = 1;
return tag;
}
/** Append a tag to a screen.
* \param tag the tag to append
* \param screen the screen id
*/
void
tag_append_to_screen(tag_t *tag, int screen)
{
int phys_screen = screen_virttophys(screen);
tag->screen = screen;
tag_list_append(&globalconf.screens[screen].tags, tag);
tag_ref(&tag);
ewmh_update_net_numbers_of_desktop(phys_screen);
ewmh_update_net_desktop_names(phys_screen);
widget_invalidate_cache(screen, WIDGET_CACHE_TAGS);
}
/** Tag a client with specified tag.
* \param c the client to tag
* \param t the tag to tag the client with
*/
void
tag_client(client_t *c, tag_t *t)
{
tag_client_node_t *tc;
/* don't tag twice */
if(is_client_tagged(c, t))
return;
tc = p_new(tag_client_node_t, 1);
tc->client = c;
tc->tag = t;
tag_client_node_list_push(&globalconf.tclink, tc);
client_saveprops(c);
widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
globalconf.screens[c->screen].need_arrange = true;
}
/** Untag a client with specified tag.
* \param c the client to tag
* \param t the tag to tag the client with
*/
void
untag_client(client_t *c, tag_t *t)
{
tag_client_node_t *tc;
for(tc = globalconf.tclink; tc; tc = tc->next)
if(tc->client == c && tc->tag == t)
{
tag_client_node_list_detach(&globalconf.tclink, tc);
p_delete(&tc);
client_saveprops(c);
widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
globalconf.screens[c->screen].need_arrange = True;
break;
}
}
/** Check if a client is tagged with the specified tag.
* \param c the client
* \param t the tag
* \return true if the client is tagged with the tag, false otherwise.
*/
bool
is_client_tagged(client_t *c, tag_t *t)
{
tag_client_node_t *tc;
if(!c)
return false;
for(tc = globalconf.tclink; tc; tc = tc->next)
if(tc->client == c && tc->tag == t)
return true;
return false;
}
/** Tag the client with the currently selected (visible) tags.
* \param c the client
*/
void
tag_client_with_current_selected(client_t *c)
{
tag_t *tag;
screen_t vscreen = globalconf.screens[c->screen];
for(tag = vscreen.tags; tag; tag = tag->next)
if(tag->selected)
tag_client(c, tag);
else
untag_client(c, tag);
}
/** Get the current tags for the specified screen.
* Returned pointer must be p_delete'd after.
* \param screen screen id
* \return a double pointer of tag list finished with a NULL element
*/
tag_t **
tags_get_current(int screen)
{
tag_t *tag, **tags = NULL;
int n = 1;
tags = p_new(tag_t *, n);
for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
if(tag->selected)
{
p_realloc(&tags, ++n);
tags[n - 2] = tag;
}
/* finish with null */
tags[n - 1] = NULL;
return tags;
}
/** Set a tag to be the only one viewed.
* \param target the tag to see
*/
static void
tag_view_only(tag_t *target)
{
tag_t *tag;
if(!target) return;
for(tag = globalconf.screens[target->screen].tags; tag; tag = tag->next)
tag_view(tag, tag == target);
}
/** View only a tag, selected by its index.
* \param screen screen id
* \param dindex the index
*/
void
tag_view_only_byindex(int screen, int dindex)
{
tag_t *tag;
if(dindex < 0)
return;
for(tag = globalconf.screens[screen].tags; tag && dindex > 0;
tag = tag->next, dindex--);
tag_view_only(tag);
}
/** Check for tag equality.
* \param Another tag.
* \return True if tags are equals.
*/
static int
luaA_tag_eq(lua_State *L)
{
tag_t **t1 = luaA_checkudata(L, 1, "tag");
tag_t **t2 = luaA_checkudata(L, 2, "tag");
lua_pushboolean(L, (*t1 == *t2));
return 1;
}
/** Convert a tag to a printable string.
* \return A string.
*/
static int
luaA_tag_tostring(lua_State *L)
{
tag_t **p = luaA_checkudata(L, 1, "tag");
lua_pushfstring(L, "[tag udata(%p) name(%s)]", *p, (*p)->name);
return 1;
}
/** Add a tag to a screen.
* \param A screen number.
*/
static int
luaA_tag_add(lua_State *L)
{
tag_t *t, **tag = luaA_checkudata(L, 1, "tag");
int i, screen = luaL_checknumber(L, 2) - 1;
luaA_checkscreen(screen);
for(i = 0; i < globalconf.screens_info->nscreen; i++)
for(t = globalconf.screens[i].tags; t; t = t->next)
if(*tag == t)
luaL_error(L, "tag already on screen %d", i + 1);
(*tag)->screen = screen;
tag_append_to_screen(*tag, screen);
return 0;
}
/** Get all tags from a screen.
* \param A screen number.
* \return A table with all tags from the screen specified.
*/
static int
luaA_tag_get(lua_State *L)
{
int screen = luaL_checknumber(L, 1) - 1;
tag_t *tag;
int i = 1;
luaA_checkscreen(screen);
lua_newtable(L);
for(tag = globalconf.screens[screen].tags; tag; tag = tag->next)
{
luaA_tag_userdata_new(tag);
lua_rawseti(L, -2, i++);
}
return 1;
}
/** Create a new tag.
* \param A table with at least a name attribute.
* Optionnal attributes are: mwfact, ncol, nmaster and layout.
* \return A new tag object.
*/
static int
luaA_tag_new(lua_State *L)
{
tag_t *tag;
int ncol, nmaster;
const char *name, *lay;
double mwfact;
layout_t *layout;
luaA_checktable(L, 1);
name = luaA_name_init(L);
mwfact = luaA_getopt_number(L, 1, "mwfact", 0.5);
ncol = luaA_getopt_number(L, 1, "ncol", 1);
nmaster = luaA_getopt_number(L, 1, "nmaster", 1);
lay = luaA_getopt_string(L, 1, "layout", "tile");
layout = name_func_lookup(lay, LayoutList);
tag = tag_new(name,
layout,
mwfact, nmaster, ncol);
return luaA_tag_userdata_new(tag);
}
/** Add or remove a tag from the current view.
* \param A boolean value, true to view tag, false otherwise.
*/
static int
luaA_tag_view(lua_State *L)
{
tag_t **tag = luaA_checkudata(L, 1, "tag");
bool view = luaA_checkboolean(L, 2);
tag_view(*tag, view);
return 0;
}
/** Get the tag selection attribute.
* \return True if the tag is viewed, false otherwise.
*/
static int
luaA_tag_isselected(lua_State *L)
{
tag_t **tag = luaA_checkudata(L, 1, "tag");
lua_pushboolean(L, (*tag)->selected);
return 1;
}
/** Set the tag master width factor. This value is used in various layouts to
* determine the size of the master window.
* \param The master width ratio value, between 0 and 1.
*/
static int
luaA_tag_mwfact_set(lua_State *L)
{
tag_t **tag = luaA_checkudata(L, 1, "tag");
double mwfact = luaL_checknumber(L, 2);
if(mwfact < 1 && mwfact > 0)
{
(*tag)->mwfact = mwfact;
globalconf.screens[(*tag)->screen].need_arrange = true;
}
else
luaL_error(L, "bad value, must be between 0 and 1");
return 0;
}
/** Get the tag master width factor.
* \return The master width ratio value.
*/
static int
luaA_tag_mwfact_get(lua_State *L)
{
tag_t **tag = luaA_checkudata(L, 1, "tag");
lua_pushnumber(L, (*tag)->mwfact);
return 1;
}
/** Set the number of columns. This is used in various layouts to set the number
* of columns used to display non-master windows.
* \param The number of columns, at least 1.
*/
static int
luaA_tag_ncol_set(lua_State *L)
{
tag_t **tag = luaA_checkudata(L, 1, "tag");
int ncol = luaL_checknumber(L, 2);
if(ncol >= 1)
{
(*tag)->ncol = ncol;
globalconf.screens[(*tag)->screen].need_arrange = true;
}
else
luaL_error(L, "bad value, must be greater than 1");
return 0;
}
/** Get the number of columns used to display non-master windows on this tag.
* \return The number of column.
*/
static int
luaA_tag_ncol_get(lua_State *L)
{
tag_t **tag = luaA_checkudata(L, 1, "tag");
lua_pushnumber(L, (*tag)->ncol);
return 1;
}
/** Set the number of master windows. This is used in various layouts to
* determine how many windows are in the master area.
* \param The number of master windows.
*/
static int
luaA_tag_nmaster_set(lua_State *L)
{
tag_t **tag = luaA_checkudata(L, 1, "tag");
int nmaster = luaL_checknumber(L, 2);
if(nmaster >= 0)
{
(*tag)->nmaster = nmaster;
globalconf.screens[(*tag)->screen].need_arrange = true;
}
else
luaL_error(L, "bad value, must be greater than 0");
return 0;
}
/** Get the number of master windows of the tag.
* \return The number of master windows.
*/
static int
luaA_tag_nmaster_get(lua_State *L)
{
tag_t **tag = luaA_checkudata(L, 1, "tag");
lua_pushnumber(L, (*tag)->nmaster);
return 1;
}
/** Get the tag name.
* \return The tag name.
*/
static int
luaA_tag_name_get(lua_State *L)
{
tag_t **tag = luaA_checkudata(L, 1, "tag");
lua_pushstring(L, (*tag)->name);
return 1;
}
/** Set the tag name.
* \param A string with the new tag name.
*/
static int
luaA_tag_name_set(lua_State *L)
{
tag_t **tag = luaA_checkudata(L, 1, "tag");
const char *name = luaL_checkstring(L, 2);
p_delete(&(*tag)->name);
(*tag)->name = a_strdup(name);
return 0;
}
/** Handle tag garbage collection.
*/
static int
luaA_tag_gc(lua_State *L)
{
tag_t **tag = luaA_checkudata(L, 1, "tag");
tag_unref(tag);
*tag = NULL;
return 0;
}
/** Get the layout of the tag.
* \return The layout name.
*/
static int
luaA_tag_layout_get(lua_State *L)
{
tag_t **tag = luaA_checkudata(L, 1, "tag");
const char *name = a_strdup(name_func_rlookup((*tag)->layout, LayoutList));
lua_pushstring(L, name);
return 1;
}
/** Set the layout of the tag.
* \param A layout name.
*/
static int
luaA_tag_layout_set(lua_State *L)
{
tag_t **tag = luaA_checkudata(L, 1, "tag");
const char *name = luaL_checkstring(L, 2);
layout_t *l = name_func_lookup(name, LayoutList);
if(l)
{
(*tag)->layout = l;
globalconf.screens[(*tag)->screen].need_arrange = true;
}
else
luaL_error(L, "unknown layout: %s", name);
return 0;
}
/** Create a new userdata from a tag.
* \param t The tag.
* \return The luaA_settype returnn value.
*/
int
luaA_tag_userdata_new(tag_t *t)
{
tag_t **lt = lua_newuserdata(globalconf.L, sizeof(tag_t *));
*lt = t;
tag_ref(lt);
return luaA_settype(globalconf.L, "tag");
}
const struct luaL_reg awesome_tag_methods[] =
{
{ "new", luaA_tag_new },
{ "get", luaA_tag_get},
{ NULL, NULL }
};
const struct luaL_reg awesome_tag_meta[] =
{
{ "add", luaA_tag_add },
{ "view", luaA_tag_view },
{ "isselected", luaA_tag_isselected },
{ "mwfact_set", luaA_tag_mwfact_set },
{ "mwfact_get", luaA_tag_mwfact_get },
{ "ncol_set", luaA_tag_ncol_set },
{ "ncol_get", luaA_tag_ncol_get },
{ "nmaster_set", luaA_tag_nmaster_set },
{ "nmaster_get", luaA_tag_nmaster_get },
{ "name_get", luaA_tag_name_get },
{ "name_set", luaA_tag_name_set },
{ "layout_get", luaA_tag_layout_get },
{ "layout_set", luaA_tag_layout_set },
{ "__eq", luaA_tag_eq },
{ "__gc", luaA_tag_gc },
{ "__tostring", luaA_tag_tostring },
{ NULL, NULL },
};
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -1,5 +1,5 @@
/*
* workspace.h - workspace management header
* tag.h - tag management header
*
* Copyright © 2007-2008 Julien Danjou <julien@danjou.info>
*
@ -19,8 +19,8 @@
*
*/
#ifndef AWESOME_WORKSPACE_H
#define AWESOME_WORKSPACE_H
#ifndef AWESOME_TAG_H
#define AWESOME_TAG_H
#include "structs.h"
#include "common/refcount.h"
@ -29,26 +29,28 @@
#define IS_TILED(client, screen) (client && !client->isfloating && !client->ismax && client_isvisible(client, screen))
/* Contructor, destructor and referencors */
workspace_t * workspace_new(const char *, layout_t *, double, int, int);
tag_t * tag_new(const char *, layout_t *, double, int, int);
static inline void
workspace_delete(workspace_t **workspace)
tag_delete(tag_t **tag)
{
p_delete(&(*workspace)->name);
p_delete(workspace);
p_delete(&(*tag)->name);
p_delete(tag);
}
void workspace_client_set(client_t *, workspace_t *);
workspace_t * workspace_client_get(client_t *);
void workspace_client_remove(client_t *);
int workspace_screen_get(workspace_t *);
tag_t ** tags_get_current(int);
void tag_client(client_t *, tag_t *);
void untag_client(client_t *, tag_t *);
bool is_client_tagged(client_t *, tag_t *);
void tag_client_with_current_selected(client_t *);
void tag_view_only_byindex(int, int);
void tag_append_to_screen(tag_t *, int);
int luaA_tag_userdata_new(tag_t *);
int luaA_workspace_userdata_new(workspace_t *);
DO_RCNT(tag_t, tag, tag_delete)
DO_SLIST(tag_t, tag, tag_delete)
DO_RCNT(workspace_t, workspace, workspace_delete)
DO_SLIST(workspace_t, workspace, workspace_delete)
DO_SLIST(workspace_client_node_t, workspace_client_node, p_delete)
DO_SLIST(tag_client_node_t, tag_client_node, p_delete)
#endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -28,7 +28,6 @@
#include "client.h"
#include "screen.h"
#include "widget.h"
#include "workspace.h"
#include "layouts/floating.h"
extern awesome_t globalconf;
@ -111,7 +110,7 @@ titlebar_draw(client_t *c)
}
widget_render(c->titlebar->widgets, ctx, c->titlebar->sw->gc, c->titlebar->sw->pixmap,
workspace_screen_get(workspace_client_get(c)), c->titlebar->position,
c->screen, c->titlebar->position,
c->titlebar->sw->geometry.x, c->titlebar->sw->geometry.y, c->titlebar);
switch(c->titlebar->position)

View File

@ -248,25 +248,24 @@ widget_common_new(widget_t *widget)
/** Invalidate widgets which should be refresh upon
* external modifications. widget_t who watch flags will
* be set to be refreshed.
* \param screen Virtual screen number.
* \param flags Cache flags to invalidate.
*/
void
widget_invalidate_cache(int flags)
widget_invalidate_cache(int screen, int flags)
{
statusbar_t *statusbar;
widget_node_t *widget;
int screen;
for(screen = 0; screen < globalconf.screens_info->nscreen; screen++)
for(statusbar = globalconf.screens[screen].statusbar;
statusbar;
statusbar = statusbar->next)
for(widget = statusbar->widgets; widget; widget = widget->next)
if(widget->widget->cache_flags & flags)
{
statusbar->need_update = true;
break;
}
for(statusbar = globalconf.screens[screen].statusbar;
statusbar;
statusbar = statusbar->next)
for(widget = statusbar->widgets; widget; widget = widget->next)
if(widget->widget->cache_flags & flags)
{
statusbar->need_update = true;
break;
}
}
/** Set a statusbar needs update because it has widget, or redraw a titlebar.

View File

@ -27,12 +27,12 @@
#define WIDGET_CACHE_CLIENTS 1<<0
#define WIDGET_CACHE_LAYOUTS 1<<1
#define WIDGET_CACHE_WORKSPACES 1<<2
#define WIDGET_CACHE_ALL (WIDGET_CACHE_CLIENTS | WIDGET_CACHE_LAYOUTS | WIDGET_CACHE_WORKSPACES)
#define WIDGET_CACHE_TAGS 1<<2
#define WIDGET_CACHE_ALL (WIDGET_CACHE_CLIENTS | WIDGET_CACHE_LAYOUTS | WIDGET_CACHE_TAGS)
typedef widget_t *(widget_constructor_t)(alignment_t);
void widget_invalidate_cache(int);
void widget_invalidate_cache(int, int);
int widget_calculate_offset(int, int, int, int);
void widget_common_new(widget_t *);
widget_t * widget_getbyname(const char *);
@ -41,7 +41,7 @@ void widget_render(widget_node_t *, draw_context_t *, xcb_gcontext_t, xcb_drawab
int luaA_widget_userdata_new(widget_t *);
widget_constructor_t workspacelist_new;
widget_constructor_t taglist_new;
widget_constructor_t textbox_new;
widget_constructor_t iconbox_new;
widget_constructor_t progressbar_new;

View File

@ -1,7 +1,6 @@
/*
* workspacelist.c - workspace list widget
* taglist.c - tag list widget
*
* Copyright © 2008 Julien Danjou <julien@danjou.info>
* Copyright © 2007 Aldo Cortesi <aldo@nullcube.com>
*
* This program is free software; you can redistribute it and/or modify
@ -22,7 +21,7 @@
#include "client.h"
#include "widget.h"
#include "workspace.h"
#include "tag.h"
#include "lua.h"
#include "event.h"
#include "common/markup.h"
@ -30,26 +29,26 @@
extern awesome_t globalconf;
typedef struct workspacelist_drawn_area_t workspacelist_drawn_area_t;
struct workspacelist_drawn_area_t
typedef struct taglist_drawn_area_t taglist_drawn_area_t;
struct taglist_drawn_area_t
{
void *object;
area_t *area;
workspacelist_drawn_area_t *next, *prev;
taglist_drawn_area_t *next, *prev;
};
DO_SLIST(workspacelist_drawn_area_t, workspacelist_drawn_area, p_delete);
DO_SLIST(taglist_drawn_area_t, taglist_drawn_area, p_delete);
typedef struct
{
char *text_normal, *text_focus, *text_urgent;
bool show_empty;
workspacelist_drawn_area_t *drawn_area;
taglist_drawn_area_t *drawn_area;
} workspacelist_data_t;
} taglist_data_t;
static char *
workspace_markup_parse(workspace_t *t, const char *str, ssize_t len)
tag_markup_parse(tag_t *t, const char *str, ssize_t len)
{
const char *elements[] = { "title", NULL };
char *title_esc = g_markup_escape_text(t->name, -1);
@ -73,88 +72,89 @@ workspace_markup_parse(workspace_t *t, const char *str, ssize_t len)
return ret;
}
/** Check if at least one client is on the workspace.
* \param ws The workspace.
* \return True or false.
/** Check if at least one client is tagged with tag number t and is on screen
* screen
* \param t tag
* \return true or false
*/
static bool
workspace_isoccupied(workspace_t *ws)
tag_isoccupied(tag_t *t)
{
client_t *c;
for(c = globalconf.clients; c; c = c->next)
if(workspace_client_get(c) == ws)
if(is_client_tagged(c, t) && !c->skip)
return true;
return false;
}
static bool
workspace_isurgent(workspace_t *ws)
tag_isurgent(tag_t *t)
{
client_t *c;
for(c = globalconf.clients; c; c = c->next)
if(c->isurgent && workspace_client_get(c) == ws)
if(is_client_tagged(c, t) && c->isurgent)
return true;
return false;
}
static char *
workspacelist_text_get(workspace_t *ws, screen_t *screen, workspacelist_data_t *data)
taglist_text_get(tag_t *tag, taglist_data_t *data)
{
if(screen->workspace == ws)
if(tag->selected)
return data->text_focus;
if(workspace_isurgent(ws))
else if(tag_isurgent(tag))
return data->text_urgent;
return data->text_normal;
}
static int
workspacelist_draw(draw_context_t *ctx, int screen,
widget_node_t *w,
int offset,
int used __attribute__ ((unused)),
void *object)
taglist_draw(draw_context_t *ctx, int screen, widget_node_t *w,
int offset,
int used __attribute__ ((unused)),
void *object)
{
workspace_t *ws;
workspacelist_data_t *data = w->widget->data;
tag_t *tag;
taglist_data_t *data = w->widget->data;
client_t *sel = globalconf.focus->client;
screen_t *vscreen = &globalconf.screens[screen];
int i = 0, prev_width = 0;
area_t *area, rectangle = { 0, 0, 0, 0, NULL, NULL };
char **text = NULL;
workspacelist_drawn_area_t *tda;
taglist_drawn_area_t *tda;
w->area.width = w->area.y = 0;
/* Lookup for our workspacelist_drawn_area.
* This will be used to store area where we draw ws list for each object. */
/* Lookup for our taglist_drawn_area.
* This will be used to store area where we draw tag list for each object. */
for(tda = data->drawn_area; tda && tda->object != object; tda = tda->next);
/* Oh, we did not find a drawn area for our object. First time? */
if(!tda)
{
/** \todo delete this when the widget is removed from the object */
tda = p_new(workspacelist_drawn_area_t, 1);
tda = p_new(taglist_drawn_area_t, 1);
tda->object = object;
workspacelist_drawn_area_list_push(&data->drawn_area, tda);
taglist_drawn_area_list_push(&data->drawn_area, tda);
}
area_list_wipe(&tda->area);
/* First compute text and widget width */
for(ws = globalconf.workspaces; ws; ws = ws->next, i++)
for(tag = vscreen->tags; tag; tag = tag->next, i++)
{
p_realloc(&text, i + 1);
area = p_new(area_t, 1);
text[i] = workspacelist_text_get(ws, &globalconf.screens[screen], data);
text[i] = workspace_markup_parse(ws, text[i], a_strlen(text[i]));
text[i] = taglist_text_get(tag, data);
text[i] = tag_markup_parse(tag, text[i], a_strlen(text[i]));
*area = draw_text_extents(ctx->connection, ctx->phys_screen,
globalconf.font, text[i]);
if (data->show_empty || workspace_isoccupied(ws))
if (data->show_empty || tag->selected || tag_isoccupied(tag))
w->area.width += area->width;
area_list_append(&tda->area, area);
@ -164,11 +164,11 @@ workspacelist_draw(draw_context_t *ctx, int screen,
w->area.x = widget_calculate_offset(ctx->width, w->area.width,
offset, w->widget->align);
for(area = tda->area, ws = globalconf.workspaces, i = 0;
ws && area;
ws = ws->next, area = area->next, i++)
for(area = tda->area, tag = vscreen->tags, i = 0;
tag && area;
tag = tag->next, area = area->next, i++)
{
if (!data->show_empty && !workspace_isoccupied(ws))
if (!data->show_empty && !tag->selected && !tag_isoccupied(tag))
continue;
area->x = w->area.x + prev_width;
@ -176,12 +176,13 @@ workspacelist_draw(draw_context_t *ctx, int screen,
draw_text(ctx, globalconf.font, *area, text[i]);
p_delete(&text[i]);
if(workspace_isoccupied(ws))
if(tag_isoccupied(tag))
{
rectangle.width = rectangle.height = (globalconf.font->height + 2) / 3;
rectangle.x = area->x;
rectangle.y = area->y;
draw_rectangle(ctx, rectangle, 1.0, false, ctx->fg);
draw_rectangle(ctx, rectangle, 1.0,
sel && is_client_tagged(sel, tag), ctx->fg);
}
}
@ -199,17 +200,18 @@ workspacelist_draw(draw_context_t *ctx, int screen,
* \param type The type object.
*/
static void
workspacelist_button_press(widget_node_t *w,
xcb_button_press_event_t *ev,
int screen __attribute__ ((unused)),
void *object,
awesome_type_t type)
taglist_button_press(widget_node_t *w,
xcb_button_press_event_t *ev,
int screen,
void *object,
awesome_type_t type)
{
screen_t *vscreen = &globalconf.screens[screen];
button_t *b;
workspacelist_data_t *data = w->widget->data;
workspacelist_drawn_area_t *tda;
taglist_data_t *data = w->widget->data;
taglist_drawn_area_t *tda;
area_t *area;
workspace_t *ws;
tag_t *tag;
/* Find the good drawn area list */
for(tda = data->drawn_area; tda && tda->object != object; tda = tda->next);
@ -217,22 +219,22 @@ workspacelist_button_press(widget_node_t *w,
for(b = w->widget->buttons; b; b = b->next)
if(ev->detail == b->button && CLEANMASK(ev->state) == b->mod && b->fct)
for(ws = globalconf.workspaces; ws && area; ws = ws->next, area = area->next)
for(tag = vscreen->tags; tag && area; tag = tag->next, area = area->next)
if(ev->event_x >= AREA_LEFT(*area)
&& ev->event_x < AREA_RIGHT(*area)
&& (data->show_empty || workspace_isoccupied(ws)) )
&& (data->show_empty || tag->selected || tag_isoccupied(tag)) )
{
luaA_pushpointer(object, type);
luaA_workspace_userdata_new(ws);
luaA_tag_userdata_new(tag);
luaA_dofunction(globalconf.L, b->fct, 2);
return;
}
}
static widget_tell_status_t
workspacelist_tell(widget_t *widget, const char *property, const char *new_value)
taglist_tell(widget_t *widget, const char *property, const char *new_value)
{
workspacelist_data_t *d = widget->data;
taglist_data_t *d = widget->data;
if(!a_strcmp(property, "text_normal"))
{
@ -258,26 +260,26 @@ workspacelist_tell(widget_t *widget, const char *property, const char *new_value
}
widget_t *
workspacelist_new(alignment_t align)
taglist_new(alignment_t align)
{
widget_t *w;
workspacelist_data_t *d;
taglist_data_t *d;
w = p_new(widget_t, 1);
widget_common_new(w);
w->align = align;
w->draw = workspacelist_draw;
w->button_press = workspacelist_button_press;
w->tell = workspacelist_tell;
w->draw = taglist_draw;
w->button_press = taglist_button_press;
w->tell = taglist_tell;
w->data = d = p_new(workspacelist_data_t, 1);
w->data = d = p_new(taglist_data_t, 1);
d->text_normal = a_strdup(" <text align=\"center\"/><title/> ");
d->text_focus = a_strdup(" <text align=\"center\"/><title/> ");
d->text_urgent = a_strdup(" <text align=\"center\"/><title/> ");
d->show_empty = true;
/* Set cache property */
w->cache_flags = WIDGET_CACHE_WORKSPACES | WIDGET_CACHE_CLIENTS;
w->cache_flags = WIDGET_CACHE_TAGS | WIDGET_CACHE_CLIENTS;
return w;
}

View File

@ -25,6 +25,7 @@
#include "screen.h"
#include "event.h"
#include "ewmh.h"
#include "tag.h"
#include "common/configopts.h"
#include "common/markup.h"
@ -33,7 +34,7 @@ extern awesome_t globalconf;
typedef enum
{
ShowFocus,
ShowWorkspace,
ShowTags,
ShowAll,
} showclient_t;
@ -53,11 +54,11 @@ tasklist_isvisible(client_t *c, int screen, showclient_t show)
switch(show)
{
case ShowAll:
return true;
case ShowWorkspace:
return (c->screen == screen);
case ShowTags:
return client_isvisible(c, screen);
case ShowFocus:
return (c == focus_client_getcurrent(globalconf.screens[screen].workspace));
return (c == focus_get_current_client(screen));
}
return false;
}
@ -262,8 +263,8 @@ tasklist_tell(widget_t *widget, const char *property, const char *new_value)
d->show_icons = a_strtobool(new_value);
else if(!a_strcmp(property, "show"))
{
if(!a_strcmp(new_value, "workspace"))
d->show = ShowWorkspace;
if(!a_strcmp(new_value, "tags"))
d->show = ShowTags;
else if(!a_strcmp(new_value, "focus"))
d->show = ShowFocus;
else if(!a_strcmp(new_value, "all"))
@ -295,7 +296,7 @@ tasklist_new(alignment_t align __attribute__ ((unused)))
d->text_focus = a_strdup(" <title/> ");
d->text_urgent = a_strdup(" <title/> ");
d->show_icons = true;
d->show = ShowWorkspace;
d->show = ShowTags;
/* Set cache property */
w->cache_flags = WIDGET_CACHE_CLIENTS;

View File

@ -1,515 +0,0 @@
/*
* workspace.c - workspace management
*
* Copyright © 2007-2008 Julien Danjou <julien@danjou.info>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include "screen.h"
#include "workspace.h"
#include "client.h"
#include "ewmh.h"
#include "client.h"
#include "focus.h"
#include "widget.h"
#include "layouts/magnifier.h"
#include "layouts/tile.h"
#include "layouts/max.h"
#include "layouts/floating.h"
#include "layouts/fibonacci.h"
#include "layoutgen.h"
extern awesome_t globalconf;
/** View a workspace.
* \param workspace The workspace.
* \param screen The screen to view on.
*/
static void
workspace_view(workspace_t *workspace, int screen)
{
int s;
for(s = 0; s < globalconf.screens_info->nscreen; s++)
/* The workspace is already viewed on `s': switch */
if(globalconf.screens[s].workspace == workspace)
{
globalconf.screens[s].workspace = globalconf.screens[screen].workspace;
globalconf.screens[s].workspace->need_arrange = true;
}
ewmh_update_net_current_desktop(screen_virttophys(screen));
widget_invalidate_cache(WIDGET_CACHE_WORKSPACES);
globalconf.screens[screen].workspace = workspace;
workspace->need_arrange = true;
}
/** Get the display screen for a workspace.
* \param ws A workspace.
* \return A screen number.
*/
int
workspace_screen_get(workspace_t *ws)
{
int screen = 0;
for(; screen < globalconf.screens_info->nscreen; screen++)
if(globalconf.screens[screen].workspace == ws)
return screen;
return -1;
}
/** Create a new workspace. Parameteres values are checked.
* \param name workspace name
* \param layout layout to use
* \param mwfact master width factor
* \param nmaster number of master windows
* \param ncol number of columns for slaves windows
* \return a new workspace with all these parameters
*/
workspace_t *
workspace_new(const char *name, layout_t *layout, double mwfact, int nmaster, int ncol)
{
workspace_t *workspace;
workspace = p_new(workspace_t, 1);
workspace->name = a_strdup(name);
workspace->layout = layout;
workspace->mwfact = mwfact;
if(workspace->mwfact <= 0 || workspace->mwfact >= 1)
workspace->mwfact = 0.5;
if((workspace->nmaster = nmaster) < 0)
workspace->nmaster = 1;
if((workspace->ncol = ncol) < 1)
workspace->ncol = 1;
return workspace;
}
static workspace_client_node_t *
workspace_client_getnode(client_t *c)
{
workspace_client_node_t *wc = NULL;
for(wc = globalconf.wclink; wc && wc->client != c; wc = wc->next);
return wc;
}
workspace_t *
workspace_client_get(client_t *c)
{
workspace_client_node_t *wc = workspace_client_getnode(c);
if(wc && wc->client == c)
return wc->workspace;
return NULL;
}
/** Remove the client from its workspace.
* \param c The client
*/
void
workspace_client_remove(client_t *c)
{
workspace_client_node_t *wc = workspace_client_getnode(c);
if(wc && wc->client == c)
{
workspace_client_node_list_detach(&globalconf.wclink, wc);
client_saveprops(c);
widget_invalidate_cache(WIDGET_CACHE_CLIENTS);
wc->workspace->need_arrange = true;
p_delete(&wc);
}
}
/** Put a client in the specified workspace.
* \param c The client.
* \param t The workspace.
*/
void
workspace_client_set(client_t *c, workspace_t *w)
{
workspace_client_node_t *wc;
if(!(wc = workspace_client_getnode(c)))
{
wc = p_new(workspace_client_node_t, 1);
wc->client = c;
workspace_client_node_list_push(&globalconf.wclink, wc);
}
wc->workspace = w;
client_saveprops(c);
widget_invalidate_cache(WIDGET_CACHE_CLIENTS);
w->need_arrange = true;
}
/** Check for workspace equality.
* \param Another workspace.
* \return True if workspaces are equals.
*/
static int
luaA_workspace_eq(lua_State *L)
{
workspace_t **t1 = luaA_checkudata(L, 1, "workspace");
workspace_t **t2 = luaA_checkudata(L, 2, "workspace");
lua_pushboolean(L, (*t1 == *t2));
return 1;
}
/** Convert a workspace to a printable string.
* \return A string.
*/
static int
luaA_workspace_tostring(lua_State *L)
{
workspace_t **p = luaA_checkudata(L, 1, "workspace");
lua_pushfstring(L, "[workspace udata(%p) name(%s)]", *p, (*p)->name);
return 1;
}
/** Add a workspace.
*/
static int
luaA_workspace_add(lua_State *L)
{
workspace_t *t, **workspace = luaA_checkudata(L, 1, "workspace");
for(t = globalconf.workspaces; t; t = t->next)
if(*workspace == t)
luaL_error(L, "workspace already added");
workspace_list_append(&globalconf.workspaces, *workspace);
workspace_ref(workspace);
/* \todo do it for all screens */
ewmh_update_net_numbers_of_desktop(globalconf.default_screen);
ewmh_update_net_desktop_names(globalconf.default_screen);
widget_invalidate_cache(WIDGET_CACHE_WORKSPACES);
return 0;
}
/** Get all workspaces.
* \return A table with all workspaces.
*/
static int
luaA_workspace_get(lua_State *L)
{
workspace_t *workspace;
int i = 1;
lua_newtable(L);
for(workspace = globalconf.workspaces; workspace; workspace = workspace->next)
{
luaA_workspace_userdata_new(workspace);
lua_rawseti(L, -2, i++);
}
return 1;
}
/** Create a new workspace.
* \param A table with at least a name attribute.
* Optionnal attributes are: mwfact, ncol, nmaster and layout.
* \return A new workspace object.
*/
static int
luaA_workspace_new(lua_State *L)
{
workspace_t *workspace;
int ncol, nmaster;
const char *name, *lay;
double mwfact;
layout_t *layout;
luaA_checktable(L, 1);
name = luaA_name_init(L);
mwfact = luaA_getopt_number(L, 1, "mwfact", 0.5);
ncol = luaA_getopt_number(L, 1, "ncol", 1);
nmaster = luaA_getopt_number(L, 1, "nmaster", 1);
lay = luaA_getopt_string(L, 1, "layout", "tile");
layout = name_func_lookup(lay, LayoutList);
workspace = workspace_new(name,
layout,
mwfact, nmaster, ncol);
return luaA_workspace_userdata_new(workspace);
}
/** Set a workspace visible on a screen.
* \param A screen number.
*/
static int
luaA_workspace_screen_set(lua_State *L)
{
workspace_t **workspace = luaA_checkudata(L, 1, "workspace");
int screen = luaL_checknumber(L, 2) - 1;
luaA_checkscreen(screen);
workspace_view(*workspace, screen);
return 0;
}
/** Get the screen the workspace is visible on.
* \return A screen number of nil if the workspace is not visible.
*/
static int
luaA_workspace_screen_get(lua_State *L)
{
workspace_t **workspace = luaA_checkudata(L, 1, "workspace");
int screen = workspace_screen_get(*workspace);
if(screen < 0)
return 0;
lua_pushnumber(L, screen + 1);
return 1;
}
/** Give the focus to the latest focused client on a workspace.
*/
static int
luaA_workspace_focus_set(lua_State *L)
{
workspace_t **workspace = luaA_checkudata(L, 1, "workspace");
client_focus(focus_client_getcurrent(*workspace));
return 0;
}
/** Set the workspace master width factor. This value is used in various layouts to
* determine the size of the master window.
* \param The master width ratio value, between 0 and 1.
*/
static int
luaA_workspace_mwfact_set(lua_State *L)
{
workspace_t **workspace = luaA_checkudata(L, 1, "workspace");
double mwfact = luaL_checknumber(L, 2);
if(mwfact < 1 && mwfact > 0)
{
(*workspace)->mwfact = mwfact;
(*workspace)->need_arrange = true;
}
else
luaL_error(L, "bad value, must be between 0 and 1");
return 0;
}
/** Get the workspace master width factor.
* \return The master width ratio value.
*/
static int
luaA_workspace_mwfact_get(lua_State *L)
{
workspace_t **workspace = luaA_checkudata(L, 1, "workspace");
lua_pushnumber(L, (*workspace)->mwfact);
return 1;
}
/** Set the number of columns. This is used in various layouts to set the number
* of columns used to display non-master windows.
* \param The number of columns, at least 1.
*/
static int
luaA_workspace_ncol_set(lua_State *L)
{
workspace_t **workspace = luaA_checkudata(L, 1, "workspace");
int ncol = luaL_checknumber(L, 2);
if(ncol >= 1)
{
(*workspace)->ncol = ncol;
(*workspace)->need_arrange = true;
}
else
luaL_error(L, "bad value, must be greater than 1");
return 0;
}
/** Get the number of columns used to display non-master windows on this workspace.
* \return The number of column.
*/
static int
luaA_workspace_ncol_get(lua_State *L)
{
workspace_t **workspace = luaA_checkudata(L, 1, "workspace");
lua_pushnumber(L, (*workspace)->ncol);
return 1;
}
/** Set the number of master windows. This is used in various layouts to
* determine how many windows are in the master area.
* \param The number of master windows.
*/
static int
luaA_workspace_nmaster_set(lua_State *L)
{
workspace_t **workspace = luaA_checkudata(L, 1, "workspace");
int nmaster = luaL_checknumber(L, 2);
if(nmaster >= 0)
{
(*workspace)->nmaster = nmaster;
(*workspace)->need_arrange = true;
}
else
luaL_error(L, "bad value, must be greater than 0");
return 0;
}
/** Get the number of master windows of the workspace.
* \return The number of master windows.
*/
static int
luaA_workspace_nmaster_get(lua_State *L)
{
workspace_t **workspace = luaA_checkudata(L, 1, "workspace");
lua_pushnumber(L, (*workspace)->nmaster);
return 1;
}
/** Get the workspace name.
* \return The workspace name.
*/
static int
luaA_workspace_name_get(lua_State *L)
{
workspace_t **workspace = luaA_checkudata(L, 1, "workspace");
lua_pushstring(L, (*workspace)->name);
return 1;
}
/** Set the workspace name.
* \param A string with the new workspace name.
*/
static int
luaA_workspace_name_set(lua_State *L)
{
workspace_t **workspace = luaA_checkudata(L, 1, "workspace");
const char *name = luaL_checkstring(L, 2);
p_delete(&(*workspace)->name);
(*workspace)->name = a_strdup(name);
return 0;
}
/** Handle workspace garbage collection.
*/
static int
luaA_workspace_gc(lua_State *L)
{
workspace_t **workspace = luaA_checkudata(L, 1, "workspace");
workspace_unref(workspace);
*workspace = NULL;
return 0;
}
/** Get the visible workspace for a screen.
* \param A screen number.
*/
static int
luaA_workspace_visible_get(lua_State *L)
{
int screen = luaL_checknumber(L, 1) - 1;
luaA_checkscreen(screen);
if(globalconf.screens[screen].workspace)
return luaA_workspace_userdata_new(globalconf.screens[screen].workspace);
return 0;
}
/** Get the layout of the workspace.
* \return The layout name.
*/
static int
luaA_workspace_layout_get(lua_State *L)
{
workspace_t **workspace = luaA_checkudata(L, 1, "workspace");
const char *name = a_strdup(name_func_rlookup((*workspace)->layout, LayoutList));
lua_pushstring(L, name);
return 1;
}
/** Set the layout of the workspace.
* \param A layout name.
*/
static int
luaA_workspace_layout_set(lua_State *L)
{
workspace_t **workspace = luaA_checkudata(L, 1, "workspace");
const char *name = luaL_checkstring(L, 2);
layout_t *l = name_func_lookup(name, LayoutList);
if(l)
{
(*workspace)->layout = l;
(*workspace)->need_arrange = true;
}
else
luaL_error(L, "unknown layout: %s", name);
return 0;
}
/** Create a new userdata from a workspace.
* \param t The workspace.
* \return The luaA_settype return value.
*/
int
luaA_workspace_userdata_new(workspace_t *w)
{
workspace_t **ws = lua_newuserdata(globalconf.L, sizeof(workspace_t *));
*ws = w;
workspace_ref(ws);
return luaA_settype(globalconf.L, "workspace");
}
const struct luaL_reg awesome_workspace_methods[] =
{
{ "new", luaA_workspace_new },
{ "get", luaA_workspace_get},
{ "visible_get", luaA_workspace_visible_get },
{ NULL, NULL }
};
const struct luaL_reg awesome_workspace_meta[] =
{
{ "add", luaA_workspace_add },
{ "screen_set", luaA_workspace_screen_set },
{ "screen_get", luaA_workspace_screen_get },
{ "focus_set", luaA_workspace_focus_set },
{ "mwfact_set", luaA_workspace_mwfact_set },
{ "mwfact_get", luaA_workspace_mwfact_get },
{ "ncol_set", luaA_workspace_ncol_set },
{ "ncol_get", luaA_workspace_ncol_get },
{ "nmaster_set", luaA_workspace_nmaster_set },
{ "nmaster_get", luaA_workspace_nmaster_get },
{ "name_get", luaA_workspace_name_get },
{ "name_set", luaA_workspace_name_set },
{ "layout_get", luaA_workspace_layout_get },
{ "layout_set", luaA_workspace_layout_set },
{ "__eq", luaA_workspace_eq },
{ "__gc", luaA_workspace_gc },
{ "__tostring", luaA_workspace_tostring },
{ NULL, NULL },
};
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80