diff --git a/src/client.c b/src/client.c index 3fb319898a23dd82dc69702e8a296e7444b465b9..f899106925a7964c1a0fb9c0b3b412d2f82fc232 100644 --- a/src/client.c +++ b/src/client.c @@ -30,6 +30,7 @@ #include "main.h" #include "client.h" #include "frame.h" +#include "hints.h" #include "workspaces.h" #include "settings.h" #include "gtktoxevent.h" @@ -545,6 +546,23 @@ void clientGetNetStruts(Client * c) } } +static void clientSetNetActions(Client * c) +{ + Atom atoms[6]; + int i = 0; + + atoms[i++] = net_wm_action_change_desktop; + atoms[i++] = net_wm_action_close; + atoms[i++] = net_wm_action_maximize_horz; + atoms[i++] = net_wm_action_maximize_vert; + atoms[i++] = net_wm_action_stick; + if (c->has_border) + { + atoms[i++] = net_wm_action_shade; + } + XChangeProperty(dpy, c->window, net_wm_allowed_actions, XA_ATOM, 32, PropModeReplace, (unsigned char *)atoms, i); +} + static void clientWindowType(Client * c) { WindowType old_type; @@ -1377,17 +1395,18 @@ static void clientInitPosition(Client * c) void clientFrame(Window w) { - Client *c; XWindowAttributes attr; XWindowChanges wc; - unsigned long dummy; PropMwmHints *mwm_hints; - int i; - unsigned long valuemask; XSetWindowAttributes attributes; Window dummy_root; - int dummy_x, dummy_y; + Client *c; + unsigned long dummy; + unsigned long valuemask; unsigned int dummy_width, dummy_height, dummy_depth, dummy_bw; + unsigned int wm_protocols_flags = 0; + int i; + int dummy_x, dummy_y; g_return_if_fail(w != None); DBG("entering clientFrame\n"); @@ -1411,6 +1430,7 @@ void clientFrame(Window w) c->size = XAllocSizeHints(); XGetWMNormalHints(dpy, w, c->size, &dummy); XGetWindowAttributes(dpy, w, &attr); + wm_protocols_flags = getWMProtocols(dpy, c->window); c->x = attr.x; c->y = attr.y; c->width = attr.width; @@ -1427,7 +1447,7 @@ void clientFrame(Window w) { c->ncmap = 0; } - + c->type_atom = None; c->type = UNSET; c->ignore_unmap = ((attr.map_state == IsViewable) ? 1 : 0); @@ -1444,7 +1464,8 @@ void clientFrame(Window w) c->skip_taskbar = False; c->skip_pager = False; c->has_struts = False; - c->wm_takefocus = (getWMTakeFocus(dpy, c->window) ? True : False); + c->wm_takefocus = ((wm_protocols_flags & WM_PROTOCOLS_TAKE_FOCUS) ? True : False); + c->wm_delete = ((wm_protocols_flags & WM_PROTOCOLS_DELETE_WINDOW) ? True : False); c->wm_input = (getWMInput(dpy, c->window) ? True : False); mwm_hints = getMotifHints(dpy, c->window); @@ -1539,6 +1560,7 @@ void clientFrame(Window w) c->buttons[i] = XCreateSimpleWindow(dpy, c->frame, 0, 0, 1, 1, 0, 0, 0); } + clientSetNetActions(c); clientAddToList(c); clientGrabKeys(c); @@ -1800,7 +1822,14 @@ void clientClose(Client * c) DBG("entering clientClose\n"); DBG("closing client \"%s\" (%#lx)\n", c->name, c->window); - sendClientMessage(dpy, c->window, wm_protocols, wm_delete_window, NoEventMask); + if (c->wm_delete) + { + sendClientMessage(dpy, c->window, wm_protocols, wm_delete_window, NoEventMask); + } + else + { + clientKill(c); + } } void clientKill(Client * c) diff --git a/src/client.h b/src/client.h index b520fb0d63f05dabd7385609c7ec7cc102041d51..fafa68105c38499e026e8a4906bcd7ee4873df88 100644 --- a/src/client.h +++ b/src/client.h @@ -198,22 +198,23 @@ struct _Client int button_pressed[BUTTON_COUNT]; int struts[4]; char *name; - unsigned int ignore_unmap; - unsigned int managed:1; unsigned int focus:1; + unsigned int fullscreen:1; unsigned int has_border:1; - unsigned int sticky:1; + unsigned int has_struts:1; + unsigned int hidden:1; + unsigned int ignore_unmap; + unsigned int managed:1; unsigned int maximized:1; - unsigned int fullscreen:1; unsigned int shaded:1; - unsigned int visible:1; - unsigned int hidden:1; - unsigned int state_modal:1; - unsigned int skip_taskbar:1; unsigned int skip_pager:1; - unsigned int has_struts:1; - unsigned int wm_takefocus:1; + unsigned int skip_taskbar:1; + unsigned int state_modal:1; + unsigned int sticky:1; + unsigned int visible:1; + unsigned int wm_delete:1; unsigned int wm_input:1; + unsigned int wm_takefocus:1; }; extern Client *clients; diff --git a/src/hints.c b/src/hints.c index 17546dc68a370295a429149510a7580906e895dc..f1381b1e9d5d01ce6aee2c492b45a9a5edfba1d1 100644 --- a/src/hints.c +++ b/src/hints.c @@ -13,9 +13,9 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - oroborus - (c) 2001 Ken Lynch - Metacity - (c) 2001 Havoc Pennington - xfwm4 - (c) 2002 Olivier Fourdan + oroborus - (c) 2001 Ken Lynch + Metacity - (c) 2001 Havoc Pennington + xfwm4 - (c) 2002 Olivier Fourdan */ @@ -37,82 +37,89 @@ #include "hints.h" #include "debug.h" -Atom wm_state; -Atom wm_change_state; -Atom wm_delete_window; -Atom wm_takefocus; -Atom wm_protocols; -Atom wm_colormap_windows; -Atom wm_window_role; -Atom wm_client_leader; -Atom sm_client_id; +Atom gnome_panel_desktop_area; Atom motif_wm_hints; -Atom win_hints; -Atom win_state; +Atom sm_client_id; Atom win_client_list; +Atom win_desktop_button_proxy; +Atom win_hints; Atom win_layer; +Atom win_state; +Atom win_supporting_wm_check; Atom win_workspace; Atom win_workspace_count; -Atom win_desktop_button_proxy; -Atom win_supporting_wm_check; -Atom gnome_panel_desktop_area; +Atom wm_change_state; +Atom wm_client_leader; +Atom wm_colormap_windows; +Atom wm_delete_window; +Atom wm_protocols; +Atom wm_state; +Atom wm_takefocus; +Atom wm_window_role; /* freedesktop.org protocol */ - -Atom utf8_string; -Atom net_wm_name; +Atom net_active_window; +Atom net_client_list; +Atom net_client_list_stacking; Atom net_close_window; -Atom net_wm_state; -Atom motif_wm_hints; -Atom net_wm_state_shaded; -Atom net_wm_state_sticky; -Atom net_wm_state_maximized_horz; -Atom net_wm_state_maximized_vert; -Atom net_wm_state_fullscreen; -Atom net_wm_desktop; -Atom net_number_of_desktops; Atom net_current_desktop; -Atom net_desktop_viewport; Atom net_desktop_geometry; -Atom net_workarea; -Atom net_supporting_wm_check; +Atom net_desktop_viewport; +Atom net_number_of_desktops; Atom net_supported; +Atom net_supporting_wm_check; +Atom net_wm_action_change_desktop; +Atom net_wm_action_close; +Atom net_wm_action_maximize_horz; +Atom net_wm_action_maximize_vert; +Atom net_wm_action_move; +Atom net_wm_action_resize; +Atom net_wm_action_shade; +Atom net_wm_action_stick; +Atom net_wm_allowed_actions; +Atom net_wm_desktop; +Atom net_wm_icon; +Atom net_wm_icon_geometry; +Atom net_wm_icon_name; +Atom net_wm_moveresize; +Atom net_wm_name; +Atom net_wm_state; +Atom net_wm_state_fullscreen; +Atom net_wm_state_hidden; +Atom net_wm_state_maximized_horz; +Atom net_wm_state_maximized_vert; +Atom net_wm_state_modal; +Atom net_wm_state_shaded; +Atom net_wm_state_skip_pager; +Atom net_wm_state_skip_taskbar; +Atom net_wm_state_sticky; +Atom net_wm_strut; Atom net_wm_window_type; Atom net_wm_window_type_desktop; +Atom net_wm_window_type_dialog; Atom net_wm_window_type_dock; -Atom net_wm_window_type_toolbar; Atom net_wm_window_type_menu; -Atom net_wm_window_type_dialog; Atom net_wm_window_type_normal; -Atom net_wm_state_modal; -Atom net_client_list; -Atom net_client_list_stacking; -Atom net_wm_state_skip_taskbar; -Atom net_wm_state_skip_pager; -Atom net_wm_icon_name; -Atom net_wm_icon; -Atom net_wm_icon_geometry; -Atom net_wm_moveresize; -Atom net_active_window; -Atom net_wm_strut; -Atom net_wm_state_hidden; -Atom net_wm_window_type_utility; Atom net_wm_window_type_splashscreen; +Atom net_wm_window_type_toolbar; +Atom net_wm_window_type_utility; +Atom net_workarea; +Atom utf8_string; void initICCCMHints(Display * dpy) { DBG("entering initICCCMHints\n"); - wm_state = XInternAtom(dpy, "WM_STATE", False); - wm_change_state = XInternAtom(dpy, "WM_CHANGE_STATE", False); - wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False); - wm_takefocus = XInternAtom(dpy, "WM_TAKE_FOCUS", False); - wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False); + sm_client_id = XInternAtom(dpy, "SM_CLIENT_ID", False); + wm_change_state = XInternAtom(dpy, "WM_CHANGE_STATE", False); + wm_client_leader = XInternAtom(dpy, "WM_CLIENT_LEADER", False); wm_colormap_windows = XInternAtom(dpy, "WM_COLORMAP_WINDOWS", False); - wm_window_role = XInternAtom(dpy, "WM_WINDOW_ROLE", False); - wm_client_leader = XInternAtom(dpy, "WM_CLIENT_LEADER", False); - sm_client_id = XInternAtom(dpy, "SM_CLIENT_ID", False); + wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False); + wm_state = XInternAtom(dpy, "WM_STATE", False); + wm_takefocus = XInternAtom(dpy, "WM_TAKE_FOCUS", False); + wm_window_role = XInternAtom(dpy, "WM_WINDOW_ROLE", False); } unsigned long getWMState(Display * dpy, Window w) @@ -126,8 +133,8 @@ unsigned long getWMState(Display * dpy, Window w) if((XGetWindowProperty(dpy, w, wm_state, 0, 2L, False, wm_state, &real_type, &real_format, &items_read, &items_left, (unsigned char **)&data) == Success) && (items_read)) { - state = *data; - XFree(data); + state = *data; + XFree(data); } return (state); } @@ -162,11 +169,11 @@ PropMwmHints *getMotifHints(Display * dpy, Window w) if((XGetWindowProperty(dpy, w, motif_wm_hints, 0L, 20L, False, motif_wm_hints, &real_type, &real_format, &items_read, &items_left, (unsigned char **)&data) == Success) && (items_read)) { - return (data); + return (data); } else { - return (NULL); + return (NULL); } } @@ -181,48 +188,56 @@ int getWMInput(Display * dpy, Window w) result = ((!(wmhints) || ((wmhints) && !(wmhints->flags & InputHint)) || ((wmhints) && (wmhints->flags & InputHint) && (wmhints->input)))); if(wmhints) { - XFree(wmhints); + XFree(wmhints); } return (result); } -int getWMTakeFocus(Display * dpy, Window w) +unsigned int getWMProtocols(Display * dpy, Window w) { Atom *protocols = None, *ap; int i, n; Atom atype; int aformat; - int result = False; + int result = 0; unsigned long bytes_remain, nitems; - DBG("entering getWMTakeFocus\n"); + DBG("entering getWMProtocols\n"); if(XGetWMProtocols(dpy, w, &protocols, &n)) { - for(i = 0, ap = protocols; i < n; i++, ap++) - { - if(*ap == (Atom) wm_takefocus) - { - result = True; - } - } + for(i = 0, ap = protocols; i < n; i++, ap++) + { + if(*ap == (Atom) wm_takefocus) + { + result |= WM_PROTOCOLS_TAKE_FOCUS; + } + if(*ap == (Atom) wm_delete_window) + { + result |= WM_PROTOCOLS_DELETE_WINDOW; + } + } } else { - if((XGetWindowProperty(dpy, w, wm_protocols, 0L, 10L, False, wm_protocols, &atype, &aformat, &nitems, &bytes_remain, (unsigned char **)&protocols)) == Success) - { - for(i = 0, ap = protocols; i < nitems; i++, ap++) - { - if(*ap == (Atom) wm_takefocus) - { - result = True; - } - } - } + if((XGetWindowProperty(dpy, w, wm_protocols, 0L, 10L, False, wm_protocols, &atype, &aformat, &nitems, &bytes_remain, (unsigned char **)&protocols)) == Success) + { + for(i = 0, ap = protocols; i < nitems; i++, ap++) + { + if(*ap == (Atom) wm_takefocus) + { + result |= WM_PROTOCOLS_TAKE_FOCUS; + } + if(*ap == (Atom) wm_delete_window) + { + result |= WM_PROTOCOLS_DELETE_WINDOW; + } + } + } } if(protocols) { - XFree(protocols); + XFree(protocols); } return (result); } @@ -232,15 +247,15 @@ void initGnomeHints(Display * dpy) { DBG("entering initGnomeHints\n"); - win_hints = XInternAtom(dpy, "_WIN_HINTS", False); - win_state = XInternAtom(dpy, "_WIN_STATE", False); - win_client_list = XInternAtom(dpy, "_WIN_CLIENT_LIST", False); - win_layer = XInternAtom(dpy, "_WIN_LAYER", False); - win_workspace = XInternAtom(dpy, "_WIN_WORKSPACE", False); - win_workspace_count = XInternAtom(dpy, "_WIN_WORKSPACE_COUNT", False); - win_desktop_button_proxy = XInternAtom(dpy, "_WIN_DESKTOP_BUTTON_PROXY", False); - win_supporting_wm_check = XInternAtom(dpy, "_WIN_SUPPORTING_WM_CHECK", False); gnome_panel_desktop_area = XInternAtom(dpy, "GNOME_PANEL_DESKTOP_AREA", False); + win_client_list = XInternAtom(dpy, "_WIN_CLIENT_LIST", False); + win_desktop_button_proxy = XInternAtom(dpy, "_WIN_DESKTOP_BUTTON_PROXY", False); + win_hints = XInternAtom(dpy, "_WIN_HINTS", False); + win_layer = XInternAtom(dpy, "_WIN_LAYER", False); + win_state = XInternAtom(dpy, "_WIN_STATE", False); + win_supporting_wm_check = XInternAtom(dpy, "_WIN_SUPPORTING_WM_CHECK", False); + win_workspace_count = XInternAtom(dpy, "_WIN_WORKSPACE_COUNT", False); + win_workspace = XInternAtom(dpy, "_WIN_WORKSPACE", False); } int getGnomeHint(Display * dpy, Window w, Atom a, long *value) @@ -256,9 +271,9 @@ int getGnomeHint(Display * dpy, Window w, Atom a, long *value) if((XGetWindowProperty(dpy, w, a, 0L, 1L, False, XA_CARDINAL, &real_type, &real_format, &items_read, &items_left, (unsigned char **)&data) == Success) && (items_read)) { - *value = *data; - XFree(data); - success = True; + *value = *data; + XFree(data); + success = True; } return (success); } @@ -281,18 +296,18 @@ void getGnomeDesktopMargins(Display * dpy, CARD32 * margins) if((XGetWindowProperty(dpy, XDefaultRootWindow(dpy), gnome_panel_desktop_area, 0L, 4L, False, XA_CARDINAL, &real_type, &real_format, &items_read, &items_left, (unsigned char **)&data) == Success) && (items_read >= 4)) { - margins[0] = data[0]; - margins[1] = data[1]; - margins[2] = data[2]; - margins[3] = data[3]; - XFree(data); + margins[0] = data[0]; + margins[1] = data[1]; + margins[2] = data[2]; + margins[3] = data[3]; + XFree(data); } else { - margins[0] = 0; - margins[1] = 0; - margins[2] = 0; - margins[3] = 0; + margins[0] = 0; + margins[1] = 0; + margins[2] = 0; + margins[3] = 0; } } @@ -300,44 +315,53 @@ void initNetHints(Display * dpy) { DBG("entering initNetHints\n"); - utf8_string = XInternAtom(dpy, "UTF8_STRING", False); - net_wm_name = XInternAtom(dpy, "_NET_WM_NAME", False); - net_close_window = XInternAtom(dpy, "_NET_CLOSE_WINDOW", False); - net_wm_state = XInternAtom(dpy, "_NET_WM_STATE", False); - net_wm_state_shaded = XInternAtom(dpy, "_NET_WM_STATE_SHADED", False); - net_wm_state_sticky = XInternAtom(dpy, "_NET_WM_STATE_STICKY", False); - net_wm_state_maximized_horz = XInternAtom(dpy, "_NET_WM_STATE_MAXIMIZED_HORZ", False); - net_wm_state_maximized_vert = XInternAtom(dpy, "_NET_WM_STATE_MAXIMIZED_VERT", False); - net_wm_state_fullscreen = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); - net_wm_desktop = XInternAtom(dpy, "_NET_WM_DESKTOP", False); - net_number_of_desktops = XInternAtom(dpy, "_NET_NUMBER_OF_DESKTOPS", False); - net_current_desktop = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False); - net_desktop_viewport = XInternAtom(dpy, "_NET_DESKTOP_VIEWPORT", False); - net_desktop_geometry = XInternAtom(dpy, "_NET_DESKTOP_GEOMETRY", False); - net_workarea = XInternAtom(dpy, "_NET_WORKAREA", False); - net_supporting_wm_check = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); - net_supported = XInternAtom(dpy, "_NET_SUPPORTED", False); - net_wm_window_type = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); - net_wm_window_type_desktop = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DESKTOP", False); - net_wm_window_type_dock = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False); - net_wm_window_type_toolbar = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_TOOLBAR", False); - net_wm_window_type_menu = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_MENU", False); - net_wm_window_type_dialog = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); - net_wm_window_type_normal = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False); - net_wm_state_modal = XInternAtom(dpy, "_NET_WM_STATE_MODAL", False); - net_client_list = XInternAtom(dpy, "_NET_CLIENT_LIST", False); - net_client_list_stacking = XInternAtom(dpy, "_NET_CLIENT_LIST_STACKING", False); - net_wm_state_skip_taskbar = XInternAtom(dpy, "_NET_WM_STATE_SKIP_TASKBAR", False); - net_wm_state_skip_pager = XInternAtom(dpy, "_NET_WM_STATE_SKIP_PAGER", False); - net_wm_icon_name = XInternAtom(dpy, "_NET_WM_ICON_NAME", False); - net_wm_icon = XInternAtom(dpy, "_NET_WM_ICON", False); - net_wm_icon_geometry = XInternAtom(dpy, "_NET_WM_ICON_GEOMETRY", False); - net_wm_moveresize = XInternAtom(dpy, "_NET_WM_MOVERESIZE", False); - net_active_window = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); - net_wm_strut = XInternAtom(dpy, "_NET_WM_STRUT", False); - net_wm_state_hidden = XInternAtom(dpy, "_NET_WM_STATE_HIDDEN", False); - net_wm_window_type_utility = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_UTILITY", False); + net_active_window = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); + net_client_list_stacking = XInternAtom(dpy, "_NET_CLIENT_LIST_STACKING", False); + net_client_list = XInternAtom(dpy, "_NET_CLIENT_LIST", False); + net_close_window = XInternAtom(dpy, "_NET_CLOSE_WINDOW", False); + net_current_desktop = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False); + net_desktop_geometry = XInternAtom(dpy, "_NET_DESKTOP_GEOMETRY", False); + net_desktop_viewport = XInternAtom(dpy, "_NET_DESKTOP_VIEWPORT", False); + net_number_of_desktops = XInternAtom(dpy, "_NET_NUMBER_OF_DESKTOPS", False); + net_supported = XInternAtom(dpy, "_NET_SUPPORTED", False); + net_supporting_wm_check = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); + net_wm_action_change_desktop = XInternAtom(dpy, "_NET_WM_ACTION_CHANGE_DESKTOP", False); + net_wm_action_close = XInternAtom(dpy, "_NET_WM_ACTION_CLOSE", False); + net_wm_action_maximize_horz = XInternAtom(dpy, "_NET_WM_ACTION_MAXIMIZE_HORZ", False); + net_wm_action_maximize_vert = XInternAtom(dpy, "_NET_WM_ACTION_MAXIMIZE_VERT", False); + net_wm_action_move = XInternAtom(dpy, "_NET_WM_ACTION_MOVE", False); + net_wm_action_resize = XInternAtom(dpy, "_NET_WM_ACTION_RESIZE", False); + net_wm_action_shade = XInternAtom(dpy, "_NET_WM_ACTION_SHADE", False); + net_wm_action_stick = XInternAtom(dpy, "_NET_WM_ACTION_STICK", False); + net_wm_allowed_actions = XInternAtom(dpy, "_NET_WM_ALLOWED_ACTIONS", False); + net_wm_desktop = XInternAtom(dpy, "_NET_WM_DESKTOP", False); + net_wm_icon_geometry = XInternAtom(dpy, "_NET_WM_ICON_GEOMETRY", False); + net_wm_icon_name = XInternAtom(dpy, "_NET_WM_ICON_NAME", False); + net_wm_icon = XInternAtom(dpy, "_NET_WM_ICON", False); + net_wm_moveresize = XInternAtom(dpy, "_NET_WM_MOVERESIZE", False); + net_wm_name = XInternAtom(dpy, "_NET_WM_NAME", False); + net_wm_state_fullscreen = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); + net_wm_state_hidden = XInternAtom(dpy, "_NET_WM_STATE_HIDDEN", False); + net_wm_state_maximized_horz = XInternAtom(dpy, "_NET_WM_STATE_MAXIMIZED_HORZ", False); + net_wm_state_maximized_vert = XInternAtom(dpy, "_NET_WM_STATE_MAXIMIZED_VERT", False); + net_wm_state_modal = XInternAtom(dpy, "_NET_WM_STATE_MODAL", False); + net_wm_state_shaded = XInternAtom(dpy, "_NET_WM_STATE_SHADED", False); + net_wm_state_skip_pager = XInternAtom(dpy, "_NET_WM_STATE_SKIP_PAGER", False); + net_wm_state_skip_taskbar = XInternAtom(dpy, "_NET_WM_STATE_SKIP_TASKBAR", False); + net_wm_state_sticky = XInternAtom(dpy, "_NET_WM_STATE_STICKY", False); + net_wm_state = XInternAtom(dpy, "_NET_WM_STATE", False); + net_wm_strut = XInternAtom(dpy, "_NET_WM_STRUT", False); + net_wm_window_type_desktop = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DESKTOP", False); + net_wm_window_type_dialog = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); + net_wm_window_type_dock = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False); + net_wm_window_type_menu = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_MENU", False); + net_wm_window_type_normal = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False); net_wm_window_type_splashscreen = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_SPLASHSCREEN", False); + net_wm_window_type_toolbar = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_TOOLBAR", False); + net_wm_window_type_utility = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_UTILITY", False); + net_wm_window_type = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); + net_workarea = XInternAtom(dpy, "_NET_WORKAREA", False); + utf8_string = XInternAtom(dpy, "UTF8_STRING", False); } int getNetHint(Display * dpy, Window w, Atom a, long *value) @@ -353,55 +377,70 @@ int getNetHint(Display * dpy, Window w, Atom a, long *value) if((XGetWindowProperty(dpy, w, a, 0L, 1L, False, XA_CARDINAL, &real_type, &real_format, &items_read, &items_left, (unsigned char **)&data) == Success) && (items_read)) { - *value = *data; - XFree(data); - success = True; + *value = *data; + XFree(data); + success = True; } return (success); } void set_net_supported_hint(Display * dpy, Window root_win, Window check_win) { - Atom atoms[32]; + Atom atoms[64]; unsigned long data[1]; int i = 0; - atoms[i++] = net_wm_name; - atoms[i++] = net_close_window; - atoms[i++] = net_wm_state; - atoms[i++] = net_wm_state_shaded; - atoms[i++] = net_wm_state_sticky; - atoms[i++] = net_wm_state_maximized_vert; - atoms[i++] = net_wm_state_maximized_horz; - atoms[i++] = net_wm_state_fullscreen; - atoms[i++] = net_wm_desktop; - atoms[i++] = net_number_of_desktops; - atoms[i++] = net_current_desktop; - atoms[i++] = net_desktop_geometry; - atoms[i++] = net_desktop_viewport; - atoms[i++] = net_workarea; - atoms[i++] = net_wm_window_type; - atoms[i++] = net_wm_window_type_desktop; - atoms[i++] = net_wm_window_type_dock; - atoms[i++] = net_wm_window_type_toolbar; - atoms[i++] = net_wm_window_type_menu; - atoms[i++] = net_wm_window_type_dialog; - atoms[i++] = net_wm_window_type_normal; - atoms[i++] = net_wm_state_modal; - atoms[i++] = net_client_list_stacking; - atoms[i++] = net_client_list; - atoms[i++] = net_wm_state_skip_taskbar; - atoms[i++] = net_wm_state_skip_pager; - atoms[i++] = net_wm_strut; - /* Not supported (yet) - atoms[i++] = net_wm_moveresize; - */ - atoms[i++] = net_wm_state_hidden; - atoms[i++] = net_wm_window_type_utility; + atoms[i++] = net_active_window; + atoms[i++] = net_client_list; + atoms[i++] = net_client_list_stacking; + atoms[i++] = net_close_window; + atoms[i++] = net_current_desktop; + atoms[i++] = net_desktop_geometry; + atoms[i++] = net_desktop_viewport; + atoms[i++] = net_number_of_desktops; + atoms[i++] = net_supported; + atoms[i++] = net_supporting_wm_check; + atoms[i++] = net_wm_action_change_desktop; + atoms[i++] = net_wm_action_close; + atoms[i++] = net_wm_action_maximize_horz; + atoms[i++] = net_wm_action_maximize_vert; + atoms[i++] = net_wm_action_move; + atoms[i++] = net_wm_action_resize; + atoms[i++] = net_wm_action_shade; + atoms[i++] = net_wm_action_stick; + atoms[i++] = net_wm_allowed_actions; + atoms[i++] = net_wm_desktop; + atoms[i++] = net_wm_icon; + atoms[i++] = net_wm_icon_geometry; + atoms[i++] = net_wm_icon_name; + /* not supported yet + atoms[i++] = net_wm_moveresize; + */ + atoms[i++] = net_wm_name; + atoms[i++] = net_wm_state; + atoms[i++] = net_wm_state_fullscreen; + atoms[i++] = net_wm_state_hidden; + atoms[i++] = net_wm_state_maximized_horz; + atoms[i++] = net_wm_state_maximized_vert; + atoms[i++] = net_wm_state_modal; + atoms[i++] = net_wm_state_shaded; + atoms[i++] = net_wm_state_skip_pager; + atoms[i++] = net_wm_state_skip_taskbar; + atoms[i++] = net_wm_state_sticky; + atoms[i++] = net_wm_strut; + atoms[i++] = net_wm_window_type; + atoms[i++] = net_wm_window_type_desktop; + atoms[i++] = net_wm_window_type_dialog; + atoms[i++] = net_wm_window_type_dock; + atoms[i++] = net_wm_window_type_menu; + atoms[i++] = net_wm_window_type_normal; atoms[i++] = net_wm_window_type_splashscreen; + atoms[i++] = net_wm_window_type_toolbar; + atoms[i++] = net_wm_window_type_utility; + atoms[i++] = net_workarea; /* Apparently not required - XChangeProperty (dpy, check_win, net_supported, XA_ATOM, 32, PropModeReplace, (unsigned char *) atoms, i); + XChangeProperty (dpy, check_win, net_supported, XA_ATOM, 32, PropModeReplace, (unsigned char *) atoms, i); */ XChangeProperty(dpy, root_win, net_supported, XA_ATOM, 32, PropModeReplace, (unsigned char *)atoms, i); data[0] = check_win; @@ -412,7 +451,7 @@ static int check_type_and_format(Display * dpy, Window w, Atom a, int expected_f { if((expected_format == format) && (expected_type == type) && (n_items < 0 || n_items > 0)) { - return (True); + return (True); } return (False); } @@ -430,18 +469,18 @@ int get_atom_list(Display * dpy, Window w, Atom a, Atom ** atoms_p, int *n_atoms if((XGetWindowProperty(dpy, w, a, 0, G_MAXLONG, False, XA_ATOM, &type, &format, &n_atoms, &bytes_after, (unsigned char **)&atoms) != Success) || (type == None)) { - return (False); + return (False); } if(!check_type_and_format(dpy, w, a, 32, XA_ATOM, -1, format, type)) { - if(atoms) - { - XFree(atoms); - } - *atoms_p = NULL; - *n_atoms_p = 0; - return (False); + if(atoms) + { + XFree(atoms); + } + *atoms_p = NULL; + *n_atoms_p = 0; + return (False); } *atoms_p = atoms; @@ -463,13 +502,13 @@ int get_cardinal_list(Display * dpy, Window w, Atom xatom, unsigned long **cardi if((XGetWindowProperty(dpy, w, xatom, 0, G_MAXLONG, False, XA_CARDINAL, &type, &format, &n_cardinals, &bytes_after, (unsigned char **)&cardinals) != Success) || (type == None)) { - return False; + return False; } if(!check_type_and_format(dpy, w, xatom, 32, XA_CARDINAL, -1, format, type)) { - XFree(cardinals); - return False; + XFree(cardinals); + return False; } *cardinals_p = cardinals; @@ -488,16 +527,16 @@ void set_net_workarea(Display * dpy, Window w, int nb_workspaces, CARD32 * margi data = (unsigned long *)malloc(sizeof(unsigned long) * j * 4); if(!data) { - gdk_beep(); - return; + gdk_beep(); + return; } ptr = data; for(i = 0; i < j; i++) { - *ptr++ = margins[MARGIN_LEFT]; - *ptr++ = margins[MARGIN_TOP]; - *ptr++ = XDisplayWidth(dpy, screen) - (margins[MARGIN_LEFT] + margins[MARGIN_RIGHT]); - *ptr++ = XDisplayHeight(dpy, screen) - (margins[MARGIN_TOP] + margins[MARGIN_BOTTOM]); + *ptr++ = margins[MARGIN_LEFT]; + *ptr++ = margins[MARGIN_TOP]; + *ptr++ = XDisplayWidth(dpy, screen) - (margins[MARGIN_LEFT] + margins[MARGIN_RIGHT]); + *ptr++ = XDisplayHeight(dpy, screen) - (margins[MARGIN_TOP] + margins[MARGIN_BOTTOM]); } XChangeProperty(dpy, w, net_workarea, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, j * 4); free(data); @@ -531,7 +570,7 @@ void getTransientFor(Display * dpy, Window w, Window * transient_for) if(!XGetTransientForHint(dpy, w, transient_for)) { - *transient_for = None; + *transient_for = None; } DBG("Window (%#lx) is transient for (%#lx)\n", w, *transient_for); @@ -550,33 +589,33 @@ int get_utf8_string(Display * dpy, Window w, Atom xatom, char **str_p) *str_p = NULL; if((XGetWindowProperty(dpy, w, xatom, 0, G_MAXLONG, False, utf8_string, &type, &format, &n_items, &bytes_after, (unsigned char **)&str) != Success) || (type == None)) { - DBG("no utf8_string value provided\n"); - return False; + DBG("no utf8_string value provided\n"); + return False; } if(!check_type_and_format(dpy, w, xatom, 8, utf8_string, -1, format, type)) { - DBG("utf8_string value invalid\n"); - if(str) - { - XFree(str); - } - return False; + DBG("utf8_string value invalid\n"); + if(str) + { + XFree(str); + } + return False; } if(!g_utf8_validate(str, n_items, NULL)) { - char *name; + char *name; - name = XGetAtomName(dpy, xatom); - if(name) - { - g_message("Property %s on window (%lx) contained invalid UTF-8\n", name, w); - XFree(name); - } - XFree(str); + name = XGetAtomName(dpy, xatom); + if(name) + { + g_message("Property %s on window (%lx) contained invalid UTF-8\n", name, w); + XFree(name); + } + XFree(str); - return False; + return False; } *str_p = str; @@ -595,8 +634,8 @@ static char *text_property_to_utf8(Display * dpy, const XTextProperty * prop) list = NULL; if((count = gdk_text_property_to_utf8_list(gdk_x11_xatom_to_atom(prop->encoding), prop->format, prop->value, prop->nitems, &list)) == 0) { - DBG("gdk_text_property_to_utf8_list returned 0\n"); - return NULL; + DBG("gdk_text_property_to_utf8_list returned 0\n"); + return NULL; } retval = list[0]; list[0] = g_strdup(""); @@ -614,16 +653,16 @@ static char *get_text_property(Display * dpy, Window w, Atom a) text.nitems = 0; if(XGetTextProperty(dpy, w, &text, a)) { - retval = text_property_to_utf8(dpy, &text); - if((text.value) && (text.nitems > 0)) - { - XFree(text.value); - } + retval = text_property_to_utf8(dpy, &text); + if((text.value) && (text.nitems > 0)) + { + XFree(text.value); + } } else { - retval = NULL; - DBG("XGetTextProperty() failed\n"); + retval = NULL; + DBG("XGetTextProperty() failed\n"); } return retval; @@ -638,19 +677,19 @@ void getWindowName(Display * dpy, Window w, char **name) *name = NULL; if(get_utf8_string(dpy, w, net_wm_name, &str)) { - *name = strdup(str); - XFree(str); - return; + *name = strdup(str); + XFree(str); + return; } str = get_text_property(dpy, w, XA_WM_NAME); if(str) { - *name = strdup(str); - XFree(str); + *name = strdup(str); + XFree(str); } else { - *name = strdup(""); + *name = strdup(""); } return; diff --git a/src/hints.h b/src/hints.h index 449dce534ce528d343c15fef435dba17ca1a2ce7..006d57edacdefc3e2aca806386ba2d4e27c50712 100644 --- a/src/hints.h +++ b/src/hints.h @@ -43,6 +43,9 @@ #define WIN_HINTS_SKIP_FOCUS (1L<<0) #define WIN_HINTS_SKIP_TASKBAR (1L<<2) +#define WM_PROTOCOLS_TAKE_FOCUS (1L<<0) +#define WM_PROTOCOLS_DELETE_WINDOW (1L<<1) + #define WIN_LAYER_DESKTOP 0 #define WIN_LAYER_BELOW 2 #define WIN_LAYER_NORMAL 4 @@ -74,66 +77,74 @@ typedef struct } PropMwmHints; -extern Atom wm_state; -extern Atom wm_change_state; -extern Atom wm_delete_window; -extern Atom wm_takefocus; -extern Atom wm_protocols; -extern Atom wm_colormap_windows; -extern Atom wm_window_role; -extern Atom wm_client_leader; -extern Atom sm_client_id; +extern Atom gnome_panel_desktop_area; extern Atom motif_wm_hints; -extern Atom win_hints; -extern Atom win_state; +extern Atom sm_client_id; extern Atom win_client_list; +extern Atom win_desktop_button_proxy; +extern Atom win_hints; extern Atom win_layer; +extern Atom win_state; +extern Atom win_supporting_wm_check; extern Atom win_workspace; extern Atom win_workspace_count; -extern Atom win_desktop_button_proxy; -extern Atom win_supporting_wm_check; -extern Atom gnome_panel_desktop_area; +extern Atom wm_change_state; +extern Atom wm_client_leader; +extern Atom wm_colormap_windows; +extern Atom wm_delete_window; +extern Atom wm_protocols; +extern Atom wm_state; +extern Atom wm_takefocus; +extern Atom wm_window_role; /* freedesktop.org protocol */ -extern Atom net_wm_name; +extern Atom net_active_window; +extern Atom net_client_list; +extern Atom net_client_list_stacking; extern Atom net_close_window; -extern Atom net_wm_state; -extern Atom motif_wm_hints; -extern Atom net_wm_state_shaded; -extern Atom net_wm_state_sticky; -extern Atom net_wm_state_maximized_horz; -extern Atom net_wm_state_maximized_vert; -extern Atom net_wm_state_fullscreen; -extern Atom net_wm_desktop; -extern Atom net_number_of_desktops; extern Atom net_current_desktop; -extern Atom net_desktop_viewport; extern Atom net_desktop_geometry; -extern Atom net_workarea; -extern Atom net_supporting_wm_check; +extern Atom net_desktop_viewport; +extern Atom net_number_of_desktops; extern Atom net_supported; +extern Atom net_supporting_wm_check; +extern Atom net_wm_action_change_desktop; +extern Atom net_wm_action_close; +extern Atom net_wm_action_maximize_horz; +extern Atom net_wm_action_maximize_vert; +extern Atom net_wm_action_move; +extern Atom net_wm_action_resize; +extern Atom net_wm_action_shade; +extern Atom net_wm_action_stick; +extern Atom net_wm_allowed_actions; +extern Atom net_wm_desktop; +extern Atom net_wm_icon; +extern Atom net_wm_icon_geometry; +extern Atom net_wm_icon_name; +extern Atom net_wm_moveresize; +extern Atom net_wm_name; +extern Atom net_wm_state; +extern Atom net_wm_state_fullscreen; +extern Atom net_wm_state_hidden; +extern Atom net_wm_state_maximized_horz; +extern Atom net_wm_state_maximized_vert; +extern Atom net_wm_state_modal; +extern Atom net_wm_state_shaded; +extern Atom net_wm_state_skip_pager; +extern Atom net_wm_state_skip_taskbar; +extern Atom net_wm_state_sticky; +extern Atom net_wm_strut; extern Atom net_wm_window_type; extern Atom net_wm_window_type_desktop; +extern Atom net_wm_window_type_dialog; extern Atom net_wm_window_type_dock; -extern Atom net_wm_window_type_toolbar; extern Atom net_wm_window_type_menu; -extern Atom net_wm_window_type_dialog; extern Atom net_wm_window_type_normal; -extern Atom net_wm_state_modal; -extern Atom net_client_list; -extern Atom net_client_list_stacking; -extern Atom net_wm_state_skip_taskbar; -extern Atom net_wm_state_skip_pager; -extern Atom net_wm_icon_name; -extern Atom net_wm_icon; -extern Atom net_wm_icon_geometry; -extern Atom net_wm_moveresize; -extern Atom net_active_window; -extern Atom net_wm_strut; -extern Atom net_wm_state_hidden; -extern Atom net_wm_window_type_utility; extern Atom net_wm_window_type_splashscreen; +extern Atom net_wm_window_type_toolbar; +extern Atom net_wm_window_type_utility; +extern Atom net_workarea; void initICCCMHints(Display *); @@ -142,7 +153,7 @@ void setWMState(Display *, Window, unsigned long state); void initMotifHints(Display *); PropMwmHints *getMotifHints(Display *, Window); int getWMInput(Display *, Window); -int getWMTakeFocus(Display *, Window); +unsigned int getWMProtocols(Display *, Window); void initGnomeHints(Display *); int getGnomeHint(Display *, Window, Atom, long *); void setGnomeHint(Display *, Window, Atom, long); diff --git a/src/keyboard.c b/src/keyboard.c index 5f22c9557bf37c77f982697d4a04456dd830331e..ec7b97208243fc1ee6306ad9bbcff68810bd3a24 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -40,7 +40,7 @@ void parseKeyString(Display * dpy, MyKey * key, char *str) key->keycode = 0; key->modifier = 0; - if(!g_strcasecmp((gchar *) str, "none")) + if(!g_ascii_strcasecmp((gchar *) str, "none")) return; k = strrchr(str, '+'); diff --git a/src/parserc.c b/src/parserc.c index 448af0c4f6b7bd6ccc01a42310799f5169724fe8..8a1bf389fe4473192dc7b0d552c3e45ae081aab7 100644 --- a/src/parserc.c +++ b/src/parserc.c @@ -58,7 +58,7 @@ gboolean parseRc(gchar * file, gchar * dir, Settings rc[]) { for(i = 0; rc[i].option; i++) { - if(!g_strcasecmp(lvalue, rc[i].option)) + if(!g_ascii_strcasecmp(lvalue, rc[i].option)) { rvalue = strtok(NULL, "\n"); if(rvalue) @@ -104,7 +104,7 @@ gchar *getValue(gchar * option, Settings rc[]) for(i = 0; rc[i].option; i++) { - if(!g_strcasecmp(option, rc[i].option)) + if(!g_ascii_strcasecmp(option, rc[i].option)) { break; } diff --git a/src/settings.c b/src/settings.c index f6a40ba3b2ab00312ee96369850953d5522e15ef..71838eb8d9baa108aa4560a38f819be7cab397ae 100644 --- a/src/settings.c +++ b/src/settings.c @@ -329,11 +329,11 @@ void loadSettings() loadPixmap(dpy, &title[TITLE_5][ACTIVE], theme, "title-5-active.xpm", colsym, 16); loadPixmap(dpy, &title[TITLE_5][INACTIVE], theme, "title-5-inactive.xpm", colsym, 16); - if(!g_strcasecmp("left", getValue("title_alignment", rc))) + if(!g_ascii_strcasecmp("left", getValue("title_alignment", rc))) { title_alignment = ALIGN_LEFT; } - else if(!g_strcasecmp("right", getValue("title_alignment", rc))) + else if(!g_ascii_strcasecmp("right", getValue("title_alignment", rc))) { title_alignment = ALIGN_RIGHT; } @@ -341,7 +341,7 @@ void loadSettings() { title_alignment = ALIGN_CENTER; } - full_width_title = !g_strcasecmp("true", getValue("full_width_title", rc)); + full_width_title = !g_ascii_strcasecmp("true", getValue("full_width_title", rc)); strncpy(button_layout, getValue("button_layout", rc), 7); button_spacing = atoi(getValue("button_spacing", rc)); @@ -349,15 +349,15 @@ void loadSettings() title_vertical_offset = atoi(getValue("title_vertical_offset", rc)); box_gc = createGC(dpy, cmap, "#FFFFFF", GXxor, NULL, True); - box_resize = !g_strcasecmp("true", getValue("box_resize", rc)); - box_move = !g_strcasecmp("true", getValue("box_move", rc)); + box_resize = !g_ascii_strcasecmp("true", getValue("box_resize", rc)); + box_move = !g_ascii_strcasecmp("true", getValue("box_move", rc)); - click_to_focus = !g_strcasecmp("true", getValue("click_to_focus", rc)); - focus_new = !g_strcasecmp("true", getValue("focus_new", rc)); - raise_on_focus = !g_strcasecmp("true", getValue("raise_on_focus", rc)); + click_to_focus = !g_ascii_strcasecmp("true", getValue("click_to_focus", rc)); + focus_new = !g_ascii_strcasecmp("true", getValue("focus_new", rc)); + raise_on_focus = !g_ascii_strcasecmp("true", getValue("raise_on_focus", rc)); raise_delay = abs(atoi(getValue("raise_delay", rc))); - if(!g_strcasecmp("center_root", getValue("window_placement", rc))) + if(!g_ascii_strcasecmp("center_root", getValue("window_placement", rc))) { window_placement = PLACEMENT_ROOT; } @@ -365,18 +365,18 @@ void loadSettings() { window_placement = PLACEMENT_MOUSE; } - snap_to_border = !g_strcasecmp("true", getValue("snap_to_border", rc)); + snap_to_border = !g_ascii_strcasecmp("true", getValue("snap_to_border", rc)); snap_width = abs(atoi(getValue("snap_width", rc))); - if(!g_strcasecmp("shade", getValue("double_click_action", rc))) + if(!g_ascii_strcasecmp("shade", getValue("double_click_action", rc))) { double_click_action = ACTION_SHADE; } - else if(!g_strcasecmp("hide", getValue("double_click_action", rc))) + else if(!g_ascii_strcasecmp("hide", getValue("double_click_action", rc))) { double_click_action = ACTION_HIDE; } - else if(!g_strcasecmp("maximize", getValue("double_click_action", rc))) + else if(!g_ascii_strcasecmp("maximize", getValue("double_click_action", rc))) { double_click_action = ACTION_MAXIMIZE; } @@ -393,7 +393,7 @@ void loadSettings() data[0] = workspace_count; XChangeProperty(dpy, root, net_number_of_desktops, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); } - wrap_workspaces = !g_strcasecmp("true", getValue("wrap_workspaces", rc)); + wrap_workspaces = !g_ascii_strcasecmp("true", getValue("wrap_workspaces", rc)); parseKeyString(dpy, &keys[KEY_MOVE_UP], getValue("move_window_up_key", rc)); parseKeyString(dpy, &keys[KEY_MOVE_DOWN], getValue("move_window_down_key", rc)); parseKeyString(dpy, &keys[KEY_MOVE_LEFT], getValue("move_window_left_key", rc));