/* * Copyright (C) 2003-2011 Kim Woelders * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies of the Software, its documentation and marketing & publicity * materials, and acknowledgment shall be given in the documentation, materials * and software packages that this Software was used. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* * Extended Window Manager Hints. */ #include "E.h" #include "desktops.h" #include "e16-ecore_hints.h" #include "events.h" #include "ewins.h" #include "hints.h" /* * _NET_WM_MOVERESIZE client message actions */ #define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0 #define _NET_WM_MOVERESIZE_SIZE_TOP 1 #define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2 #define _NET_WM_MOVERESIZE_SIZE_RIGHT 3 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4 #define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6 #define _NET_WM_MOVERESIZE_SIZE_LEFT 7 #define _NET_WM_MOVERESIZE_MOVE 8 #define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 #define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 #define _NET_WM_MOVERESIZE_CANCEL 11 /* Window state property change actions */ #define _NET_WM_STATE_REMOVE 0 #define _NET_WM_STATE_ADD 1 #define _NET_WM_STATE_TOGGLE 2 /* Source indication */ #define _NET_WM_SOURCE_UNKNOWN 0 #define _NET_WM_SOURCE_APP 1 #define _NET_WM_SOURCE_USER 2 #define OPSRC(src) (((src) == _NET_WM_SOURCE_USER) ? _NET_WM_SOURCE_USER : _NET_WM_SOURCE_APP) /* * Set/clear Atom in list */ static void atom_list_set(Ecore_X_Atom * atoms, int size, int *count, Ecore_X_Atom atom, int set) { int i, n, in_list; n = *count; /* Check if atom is in list or not (+get index) */ for (i = 0; i < n; i++) if (atoms[i] == atom) break; in_list = i < n; if (set && !in_list) { /* Add it (if space left) */ if (n < size) atoms[n++] = atom; *count = n; } else if (!set && in_list) { /* Remove it */ atoms[i] = atoms[--n]; *count = n; } } /* * Initialize EWMH stuff */ void EWMH_Init(Window win_wm_check) { Ecore_X_Atom atom_list[64]; int atom_count; #ifndef USE_ECORE_X ecore_x_netwm_init(); #endif atom_count = 0; atom_list[atom_count++] = ECORE_X_ATOM_NET_SUPPORTED; atom_list[atom_count++] = ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK; atom_list[atom_count++] = ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS; atom_list[atom_count++] = ECORE_X_ATOM_NET_DESKTOP_GEOMETRY; atom_list[atom_count++] = ECORE_X_ATOM_NET_DESKTOP_NAMES; atom_list[atom_count++] = ECORE_X_ATOM_NET_CURRENT_DESKTOP; atom_list[atom_count++] = ECORE_X_ATOM_NET_DESKTOP_VIEWPORT; atom_list[atom_count++] = ECORE_X_ATOM_NET_WORKAREA; atom_list[atom_count++] = ECORE_X_ATOM_NET_VIRTUAL_ROOTS; atom_list[atom_count++] = ECORE_X_ATOM_NET_SHOWING_DESKTOP; atom_list[atom_count++] = ECORE_X_ATOM_NET_ACTIVE_WINDOW; atom_list[atom_count++] = ECORE_X_ATOM_NET_CLIENT_LIST; atom_list[atom_count++] = ECORE_X_ATOM_NET_CLIENT_LIST_STACKING; atom_list[atom_count++] = ECORE_X_ATOM_NET_CLOSE_WINDOW; atom_list[atom_count++] = ECORE_X_ATOM_NET_MOVERESIZE_WINDOW; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_MOVERESIZE; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_NAME; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_ICON_NAME; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_DESKTOP; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_WINDOW_TYPE; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_STATE; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_STATE_MODAL; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_STATE_STICKY; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_STATE_SHADED; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_STATE_HIDDEN; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_STATE_ABOVE; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_STATE_BELOW; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_ACTION_MOVE; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_ACTION_RESIZE; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_ACTION_SHADE; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_ACTION_STICK; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_ACTION_CLOSE; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_ACTION_ABOVE; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_ACTION_BELOW; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_STRUT_PARTIAL; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_STRUT; atom_list[atom_count++] = ECORE_X_ATOM_NET_FRAME_EXTENTS; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_USER_TIME; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_USER_TIME_WINDOW; atom_list[atom_count++] = ECORE_X_ATOM_NET_WM_WINDOW_OPACITY; ecore_x_window_prop_atom_set(WinGetXwin(VROOT), ECORE_X_ATOM_NET_SUPPORTED, atom_list, atom_count); /* Set WM info properties */ ecore_x_netwm_wm_identify(WinGetXwin(VROOT), win_wm_check, e_wm_name); } /* * Desktops */ void EWMH_SetDesktopCount(void) { ecore_x_netwm_desk_count_set(WinGetXwin(VROOT), DesksGetNumber()); } void EWMH_SetDesktopRoots(void) { int i, n_desks; Ecore_X_Window *wl; n_desks = DesksGetNumber(); wl = EMALLOC(Ecore_X_Window, n_desks); if (!wl) return; for (i = 0; i < n_desks; i++) wl[i] = EoGetXwin(DeskGet(i)); ecore_x_netwm_desk_roots_set(WinGetXwin(VROOT), wl, n_desks); Efree(wl); } void EWMH_SetDesktopNames(void) { /* Fall back to defaults */ ecore_x_netwm_desk_names_set(WinGetXwin(VROOT), NULL, DesksGetNumber()); } void EWMH_SetDesktopSize(void) { int ax, ay; DesksGetAreaSize(&ax, &ay); ecore_x_netwm_desk_size_set(WinGetXwin(VROOT), ax * WinGetW(VROOT), ay * WinGetH(VROOT)); } void EWMH_SetWorkArea(void) { unsigned int *p_coord; int n_coord, i, n_desks; n_desks = DesksGetNumber(); n_coord = 4 * n_desks; p_coord = EMALLOC(unsigned int, n_coord); if (!p_coord) return; for (i = 0; i < n_desks; i++) { p_coord[4 * i] = 0; p_coord[4 * i + 1] = 0; p_coord[4 * i + 2] = WinGetW(VROOT); p_coord[4 * i + 3] = WinGetH(VROOT); } ecore_x_netwm_desk_workareas_set(WinGetXwin(VROOT), p_coord, n_desks); Efree(p_coord); } void EWMH_SetCurrentDesktop(void) { ecore_x_netwm_desk_current_set(WinGetXwin(VROOT), DesksGetCurrentNum()); } void EWMH_SetDesktopViewport(void) { unsigned int *p_coord; int n_coord, i, ax, ay, n_desks; n_desks = DesksGetNumber(); n_coord = 2 * n_desks; p_coord = EMALLOC(unsigned int, n_coord); if (!p_coord) return; for (i = 0; i < n_desks; i++) { DeskGetArea(DeskGet(i), &ax, &ay); p_coord[2 * i] = ax * WinGetW(VROOT); p_coord[2 * i + 1] = ay * WinGetH(VROOT); } ecore_x_netwm_desk_viewports_set(WinGetXwin(VROOT), p_coord, n_desks); Efree(p_coord); } void EWMH_SetShowingDesktop(int on) { ecore_x_netwm_showing_desktop_set(WinGetXwin(VROOT), on); } /* * Window status */ void EWMH_SetClientList(void) { Ecore_X_Window *wl; int i, num; EWin *const *lst; /* Mapping order */ lst = EwinListOrderGet(&num); if (num > 0) { wl = EMALLOC(Ecore_X_Window, num); for (i = 0; i < num; i++) wl[i] = EwinGetClientXwin(lst[i]); ecore_x_netwm_client_list_set(WinGetXwin(VROOT), wl, num); Efree(wl); } else { ecore_x_netwm_client_list_set(WinGetXwin(VROOT), NULL, 0); } } void EWMH_SetClientStacking(void) { Ecore_X_Window *wl; int i, num; EWin *const *lst; /* Stacking order */ lst = EwinListStackGet(&num); if (num > 0) { wl = EMALLOC(Ecore_X_Window, num); for (i = 0; i < num; i++) wl[i] = EwinGetClientXwin(lst[num - i - 1]); ecore_x_netwm_client_list_stacking_set(WinGetXwin(VROOT), wl, num); Efree(wl); } else { ecore_x_netwm_client_list_stacking_set(WinGetXwin(VROOT), NULL, 0); } } void EWMH_SetActiveWindow(Window win) { static Window win_last_set = None; if (win == win_last_set) return; ecore_x_netwm_client_active_set(WinGetXwin(VROOT), win); win_last_set = win; } /* * Functions that set X11-properties from E-window internals */ void EWMH_SetWindowName(Window win, const char *name) { const char *str; str = EstrInt2Enc(name, 1); ecore_x_netwm_name_set(win, str); EstrInt2EncFree(str, 1); } void EWMH_SetWindowDesktop(const EWin * ewin) { unsigned int val; if (EoIsSticky(ewin)) val = 0xFFFFFFFF; else val = EoGetDeskNum(ewin); ecore_x_netwm_desktop_set(EwinGetClientXwin(ewin), val); } void EWMH_SetWindowState(const EWin * ewin) { Ecore_X_Atom atom_list[64]; int len = sizeof(atom_list) / sizeof(Ecore_X_Atom); int atom_count; atom_count = 0; atom_list_set(atom_list, len, &atom_count, ECORE_X_ATOM_NET_WM_STATE_MODAL, ewin->state.modal); atom_list_set(atom_list, len, &atom_count, ECORE_X_ATOM_NET_WM_STATE_STICKY, EoIsSticky(ewin)); atom_list_set(atom_list, len, &atom_count, ECORE_X_ATOM_NET_WM_STATE_SHADED, ewin->state.shaded); atom_list_set(atom_list, len, &atom_count, ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR, ewin->props.skip_ext_task); atom_list_set(atom_list, len, &atom_count, ECORE_X_ATOM_NET_WM_STATE_HIDDEN, ewin->state.iconified || ewin->state.shaded); atom_list_set(atom_list, len, &atom_count, ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT, ewin->state.maximized_vert); atom_list_set(atom_list, len, &atom_count, ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ, ewin->state.maximized_horz); atom_list_set(atom_list, len, &atom_count, ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN, ewin->state.fullscreen); atom_list_set(atom_list, len, &atom_count, ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER, ewin->props.skip_ext_pager); atom_list_set(atom_list, len, &atom_count, ECORE_X_ATOM_NET_WM_STATE_ABOVE, EoGetLayer(ewin) >= 6); atom_list_set(atom_list, len, &atom_count, ECORE_X_ATOM_NET_WM_STATE_BELOW, EoGetLayer(ewin) <= 2); atom_list_set(atom_list, len, &atom_count, ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION, ewin->state.attention); ecore_x_window_prop_atom_set(EwinGetClientXwin(ewin), ECORE_X_ATOM_NET_WM_STATE, atom_list, atom_count); } void EWMH_SetWindowBorder(const EWin * ewin) { unsigned int val[4]; if (ewin->border) { int bl, br, bt, bb; EwinBorderGetSize(ewin, &bl, &br, &bt, &bb); val[0] = (unsigned int)bl; val[1] = (unsigned int)br; val[2] = (unsigned int)bt; val[3] = (unsigned int)bb; } else val[0] = val[1] = val[2] = val[3] = 0; ecore_x_window_prop_card32_set(EwinGetClientXwin(ewin), ECORE_X_ATOM_NET_FRAME_EXTENTS, val, 4); } void EWMH_SetWindowOpacity(const EWin * ewin) { ecore_x_netwm_opacity_set(EwinGetClientXwin(ewin), ewin->ewmh.opacity); ecore_x_netwm_opacity_set(EoGetXwin(ewin), ewin->ewmh.opacity); } /* * Functions that set E-window internals from X11-properties */ static void EWMH_GetWindowName(EWin * ewin) { char *val; _EFREE(ewin->ewmh.wm_name); ecore_x_netwm_name_get(EwinGetClientXwin(ewin), &val); if (!val) return; ewin->ewmh.wm_name = EstrUtf82Int(val, 0); Efree(val); EwinChange(ewin, EWIN_CHANGE_NAME); } static void EWMH_GetWindowIconName(EWin * ewin) { char *val; _EFREE(ewin->ewmh.wm_icon_name); ecore_x_netwm_icon_name_get(EwinGetClientXwin(ewin), &val); if (!val) return; ewin->ewmh.wm_icon_name = EstrUtf82Int(val, 0); Efree(val); EwinChange(ewin, EWIN_CHANGE_ICON_NAME); } static void EWMH_GetWindowDesktop(EWin * ewin) { int num; unsigned int desk; num = ecore_x_netwm_desktop_get(EwinGetClientXwin(ewin), &desk); if (num <= 0) return; if (desk == 0xFFFFFFFF) { /* It is possible to distinguish between "sticky" and "on all desktops". */ /* E doesn't */ EoSetSticky(ewin, 1); } else { EoSetDesk(ewin, DeskGet(desk)); EoSetSticky(ewin, 0); } EwinChange(ewin, EWIN_CHANGE_DESKTOP); } static void EWMH_GetWindowState(EWin * ewin) { Ecore_X_Atom *p_atoms, atom; int i, n_atoms; n_atoms = ecore_x_window_prop_atom_list_get(EwinGetClientXwin(ewin), ECORE_X_ATOM_NET_WM_STATE, &p_atoms); if (n_atoms <= 0) return; /* We must clear/set all according to not present/present */ /* EoSetSticky(ewin, 0); Do not override if set via _NET_WM_DESKTOP */ ewin->state.shaded = 0; ewin->state.modal = 0; ewin->props.skip_ext_task = ewin->props.skip_ext_pager = 0; ewin->state.maximized_horz = ewin->state.maximized_vert = 0; ewin->state.fullscreen = ewin->state.attention = 0; /* ewin->layer = No ... TBD */ for (i = 0; i < n_atoms; i++) { atom = p_atoms[i]; if (atom == ECORE_X_ATOM_NET_WM_STATE_MODAL) ewin->state.modal = 1; else if (atom == ECORE_X_ATOM_NET_WM_STATE_STICKY) EoSetSticky(ewin, 1); else if (atom == ECORE_X_ATOM_NET_WM_STATE_SHADED) ewin->state.shaded = 1; else if (atom == ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR) ewin->props.skip_ext_task = 1; else if (atom == ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER) ewin->props.skip_ext_pager = 1; else if (atom == ECORE_X_ATOM_NET_WM_STATE_HIDDEN) ; /* ewin->state.iconified = 1; No - WM_STATE does this */ else if (atom == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT) ewin->state.maximized_vert = 1; else if (atom == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ) ewin->state.maximized_horz = 1; else if (atom == ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN) ewin->state.fullscreen = 1; else if (atom == ECORE_X_ATOM_NET_WM_STATE_ABOVE) EoSetLayer(ewin, 6); else if (atom == ECORE_X_ATOM_NET_WM_STATE_BELOW) EoSetLayer(ewin, 2); else if (atom == ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION) ewin->state.attention = 1; } Efree(p_atoms); } static void EWMH_GetWindowType(EWin * ewin) { Ecore_X_Atom *p_atoms, atom; int n_atoms, i; ewin->ewmh.type.all = 0; n_atoms = ecore_x_window_prop_atom_list_get(EwinGetClientXwin(ewin), ECORE_X_ATOM_NET_WM_WINDOW_TYPE, &p_atoms); if (n_atoms <= 0) { if (EwinIsTransient(ewin)) ewin->ewmh.type.b.dialog = 1; else ewin->ewmh.type.b.normal = 1; return; } for (i = 0; i < n_atoms; i++) { atom = p_atoms[i]; if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP) ewin->ewmh.type.b.desktop = 1; else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK) ewin->ewmh.type.b.dock = 1; else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY) ewin->ewmh.type.b.utility = 1; else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR) ewin->ewmh.type.b.toolbar = 1; else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU) ewin->ewmh.type.b.menu = 1; else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH) ewin->ewmh.type.b.splash = 1; else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG) ewin->ewmh.type.b.dialog = 1; else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL) ewin->ewmh.type.b.normal = 1; } Efree(p_atoms); } static void EWMH_GetWindowIcons(EWin * ewin) { unsigned int *val; int num; Efree(ewin->ewmh.wm_icon); ewin->ewmh.wm_icon = NULL; num = ecore_x_window_prop_card32_list_get(EwinGetClientXwin(ewin), ECORE_X_ATOM_NET_WM_ICON, &val); ewin->ewmh.wm_icon_len = num; if (num <= 0) return; if (num < 2 || num < (int)(2 + val[0] * val[1])) { Eprintf ("*** EWMH_GetWindowIcons Icon data/size mismatch (ignoring): %s: N=%d WxH=%dx%d\n", EwinGetTitle(ewin), num, val[0], (num >= 2) ? val[1] : 0); Efree(val); return; } ewin->ewmh.wm_icon = val; EwinChange(ewin, EWIN_CHANGE_ICON_PMAP); } static void EWMH_GetWindowUserTime(EWin * ewin __UNUSED__) { #if 0 /* TBD */ int num; unsigned int ts; num = ecore_x_netwm_user_time_get(EwinGetClientXwin(ewin), &ts); if (num <= 0) return; Eprintf("EWMH_GetWindowUserTime %#x\n", ts); #endif } static void EWMH_GetWindowStartupId(EWin * ewin) { #define TryGroup(e) (((e)->icccm.group != None) && ((e)->icccm.group != EwinGetClientXwin(e))) char *str; if (!Conf.testing.enable_startup_id) return; ecore_x_netwm_startup_id_get(EwinGetClientXwin(ewin), &str); if (!str && TryGroup(ewin)) ecore_x_netwm_startup_id_get(ewin->icccm.group, &str); if (str && EDebug(1)) Eprintf("Startup id: %s: %s\n", EwinGetTitle(ewin), str); Efree(str); /* Well... just free for now */ } static void EWMH_GetWindowMisc(EWin * ewin) { int num; Ecore_X_Window win; num = ecore_x_window_prop_window_get(EwinGetClientXwin(ewin), ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK, &win, 1); if (num <= 0) return; ewin->props.vroot = 1; EoSetDesk(ewin, DesksGetCurrent()); } static void EWMH_GetWindowOpacity(EWin * ewin) { int num; unsigned int opacity; num = ecore_x_netwm_opacity_get(EwinGetClientXwin(ewin), &opacity); if (num <= 0) return; if (ewin->ewmh.opacity == opacity) return; ewin->ewmh.opacity = opacity; EwinChange(ewin, EWIN_CHANGE_OPACITY); } static void EWMH_GetWindowStrut(EWin * ewin) { int num; unsigned int val[12]; num = ecore_x_window_prop_card32_get(EwinGetClientXwin(ewin), ECORE_X_ATOM_NET_WM_STRUT_PARTIAL, val, 12); if (num < 4) num = ecore_x_window_prop_card32_get(EwinGetClientXwin(ewin), ECORE_X_ATOM_NET_WM_STRUT, val, 4); if (num < 4) return; ewin->strut.left = val[0]; ewin->strut.right = val[1]; ewin->strut.top = val[2]; ewin->strut.bottom = val[3]; #if 0 /* FIXME - Handle in placement code */ if (num < 12) return; ewin->strut.left_start_y = val[4]; ewin->strut.left_end_y = val[5]; ewin->strut.right_start_y = val[6]; ewin->strut.right_end_y = val[7]; ewin->strut.top_start_x = val[8]; ewin->strut.top_end_x = val[9]; ewin->strut.bottom_start_x = val[10]; ewin->strut.bottom_end_x = val[11]; #endif } void EWMH_SetWindowActions(const EWin * ewin) { Ecore_X_Atom aa[12]; int num; num = 0; if (!ewin->state.inhibit_move) aa[num++] = ECORE_X_ATOM_NET_WM_ACTION_MOVE; if (!ewin->state.inhibit_resize) aa[num++] = ECORE_X_ATOM_NET_WM_ACTION_RESIZE; if (!ewin->state.inhibit_iconify) aa[num++] = ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE; if (!ewin->state.inhibit_shade) aa[num++] = ECORE_X_ATOM_NET_WM_ACTION_SHADE; if (!ewin->state.inhibit_stick) aa[num++] = ECORE_X_ATOM_NET_WM_ACTION_STICK; if (!ewin->state.inhibit_max_hor) aa[num++] = ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ; if (!ewin->state.inhibit_max_ver) aa[num++] = ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT; if (!ewin->state.inhibit_fullscreeen) aa[num++] = ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN; if (!ewin->state.inhibit_change_desk) aa[num++] = ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP; if (!ewin->state.inhibit_close) aa[num++] = ECORE_X_ATOM_NET_WM_ACTION_CLOSE; if (!ewin->state.inhibit_stacking) aa[num++] = ECORE_X_ATOM_NET_WM_ACTION_ABOVE; if (!ewin->state.inhibit_stacking) aa[num++] = ECORE_X_ATOM_NET_WM_ACTION_BELOW; ecore_x_window_prop_atom_set(EwinGetClientXwin(ewin), ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS, aa, num); } void EWMH_GetWindowHints(EWin * ewin) { EWMH_GetWindowMisc(ewin); EWMH_GetWindowOpacity(ewin); EWMH_GetWindowName(ewin); EWMH_GetWindowIconName(ewin); EWMH_GetWindowDesktop(ewin); EWMH_GetWindowState(ewin); EWMH_GetWindowType(ewin); EWMH_GetWindowIcons(ewin); EWMH_GetWindowStrut(ewin); EWMH_GetWindowUserTime(ewin); EWMH_GetWindowStartupId(ewin); } /* * Delete all (_NET_...) properties set on window */ void EWMH_DelWindowHints(const EWin * ewin) { XDeleteProperty(disp, EwinGetClientXwin(ewin), ECORE_X_ATOM_NET_WM_DESKTOP); XDeleteProperty(disp, EwinGetClientXwin(ewin), ECORE_X_ATOM_NET_WM_STATE); } /* * Process property change */ int EWMH_ProcessPropertyChange(EWin * ewin, Atom atom_change) { if (atom_change == ECORE_X_ATOM_NET_WM_NAME) { EWMH_GetWindowName(ewin); return 1; } if (atom_change == ECORE_X_ATOM_NET_WM_ICON_NAME) { EWMH_GetWindowIconName(ewin); return 1; } if (atom_change == ECORE_X_ATOM_NET_WM_STRUT_PARTIAL || atom_change == ECORE_X_ATOM_NET_WM_STRUT) { EWMH_GetWindowStrut(ewin); return 1; } if (atom_change == ECORE_X_ATOM_NET_WM_WINDOW_OPACITY) { EWMH_GetWindowOpacity(ewin); return 1; } if (atom_change == ECORE_X_ATOM_NET_WM_USER_TIME) { #if 0 /* Remove? */ EWMH_GetWindowUserTime(ewin); #endif return 1; } return 0; } /* * Process configuration requests from clients */ static int do_set(int is_set, int action) { switch (action) { case _NET_WM_STATE_REMOVE: return 0; case _NET_WM_STATE_ADD: return 1; case _NET_WM_STATE_TOGGLE: return !is_set; } return -1; } int EWMH_ProcessClientClientMessage(EWin * ewin, XClientMessageEvent * ev) { int source; /* Time ts; */ if (ev->message_type == ECORE_X_ATOM_NET_ACTIVE_WINDOW) { source = OPSRC(ev->data.l[0]); /* ts = ev->data.l[1]; */ /* cwin = ev->data.l[2]; */ EwinOpActivate(ewin, source, 1); return 1; } if (ev->message_type == ECORE_X_ATOM_NET_CLOSE_WINDOW) { /* ts = ev->data.l[0]; */ source = OPSRC(ev->data.l[1]); EwinOpClose(ewin, source); return 1; } if (ev->message_type == ECORE_X_ATOM_NET_WM_DESKTOP) { source = OPSRC(ev->data.l[1]); if ((unsigned)ev->data.l[0] == 0xFFFFFFFF) { if (!EoIsSticky(ewin)) EwinOpStick(ewin, source, 1); } else { if (EoIsSticky(ewin)) EwinOpStick(ewin, source, 0); else EwinMoveToDesktop(ewin, DeskGet(ev->data.l[0])); } return 1; } if (ev->message_type == ECORE_X_ATOM_NET_WM_STATE) { /* * It is assumed(!) that only the MAXIMIZE H/V ones can be set * in one message. */ unsigned int action; Atom atom, atom2; action = ev->data.l[0]; atom = ev->data.l[1]; atom2 = ev->data.l[2]; source = OPSRC(ev->data.l[3]); if (atom == ECORE_X_ATOM_NET_WM_STATE_MODAL) { action = do_set(ewin->state.modal, action); /* TBD */ ewin->state.modal = action; } else if (atom == ECORE_X_ATOM_NET_WM_STATE_STICKY) { action = do_set(EoIsSticky(ewin), action); EwinOpStick(ewin, source, action); } else if (atom == ECORE_X_ATOM_NET_WM_STATE_SHADED) { action = do_set(ewin->state.shaded, action); EwinOpShade(ewin, source, action); } else if (atom == ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR) { action = do_set(ewin->props.skip_ext_task, action); ewin->props.skip_ext_task = action; EWMH_SetWindowState(ewin); } else if (atom == ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER) { action = do_set(ewin->props.skip_ext_pager, action); ewin->props.skip_ext_pager = action; EWMH_SetWindowState(ewin); } else if (atom == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT || atom == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ) { int maxh, maxv; maxh = ewin->state.maximized_horz; maxv = ewin->state.maximized_vert; if (atom2 == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT || atom2 == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ) { /* (ok - ok) */ maxh = do_set(maxh, action); maxv = do_set(maxv, action); } else if (atom == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT) { maxv = do_set(maxv, action); } else { maxh = do_set(maxh, action); } if ((ewin->state.maximized_horz != maxh) || (ewin->state.maximized_vert != maxv)) { MaxSizeHV(ewin, "available", maxh, maxv); EWMH_SetWindowState(ewin); } } else if (atom == ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN) { action = do_set(ewin->state.fullscreen, action); if (ewin->state.fullscreen != action) EwinOpFullscreen(ewin, source, action); } else if (atom == ECORE_X_ATOM_NET_WM_STATE_ABOVE) { action = do_set(EoGetLayer(ewin) >= 6, action); if (action) { if (EoGetLayer(ewin) < 6) EwinOpSetLayer(ewin, source, 6); } else { if (EoGetLayer(ewin) >= 6) EwinOpSetLayer(ewin, source, 4); } } else if (atom == ECORE_X_ATOM_NET_WM_STATE_BELOW) { action = do_set(EoGetLayer(ewin) <= 2, action); if (action) { if (EoGetLayer(ewin) > 2) EwinOpSetLayer(ewin, source, 2); } else { if (EoGetLayer(ewin) <= 2) EwinOpSetLayer(ewin, source, 4); } } else if (atom == ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION) { action = do_set(ewin->state.attention, action); ewin->state.attention = action; EWMH_SetWindowState(ewin); } return 1; } if (ev->message_type == ECORE_X_ATOM_NET_MOVERESIZE_WINDOW) { int flags, grav, x, y, w, h; flags = ev->data.l[0]; grav = flags & 0xf; /* 0 means use client gravity */ x = (flags & 0x0100) ? ev->data.l[1] : EoGetX(ewin); y = (flags & 0x0200) ? ev->data.l[2] : EoGetY(ewin); w = (flags & 0x0400) ? ev->data.l[3] : ewin->client.w; h = (flags & 0x0800) ? ev->data.l[4] : ewin->client.h; /* source = OPSRC((flags & 0xF000) >> 12); */ EwinMoveResizeWithGravity(ewin, x, y, w, h, grav); return 1; } if (ev->message_type == ECORE_X_ATOM_NET_WM_MOVERESIZE) { /* source = OPSRC(ev->data.l[4]); */ EventsUpdateXY(NULL, NULL); switch (ev->data.l[2]) { case _NET_WM_MOVERESIZE_SIZE_TOPLEFT: case _NET_WM_MOVERESIZE_SIZE_TOPRIGHT: case _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT: case _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT: MoveResizeResizeStart(ewin, 0, MODE_RESIZE); break; case _NET_WM_MOVERESIZE_SIZE_RIGHT: case _NET_WM_MOVERESIZE_SIZE_LEFT: MoveResizeResizeStart(ewin, 0, MODE_RESIZE_H); break; case _NET_WM_MOVERESIZE_SIZE_TOP: case _NET_WM_MOVERESIZE_SIZE_BOTTOM: MoveResizeResizeStart(ewin, 0, MODE_RESIZE_V); break; case _NET_WM_MOVERESIZE_MOVE: MoveResizeMoveStart(ewin, 0, 0, 0); break; case _NET_WM_MOVERESIZE_SIZE_KEYBOARD: MoveResizeResizeStart(ewin, 1, MODE_RESIZE); break; case _NET_WM_MOVERESIZE_MOVE_KEYBOARD: MoveResizeMoveStart(ewin, 1, 0, 0); break; case _NET_WM_MOVERESIZE_CANCEL: MoveResizeEnd(ewin); break; } return 1; } if (ev->message_type == ECORE_X_ATOM_NET_RESTACK_WINDOW) { /* source = OPSRC(ev->data.l[0]); */ /* FIXME - Implement */ return 1; } return 0; } int EWMH_ProcessRootClientMessage(XClientMessageEvent * ev) { if (ev->message_type == ECORE_X_ATOM_NET_CURRENT_DESKTOP) { DeskGotoNum(ev->data.l[0]); return 1; } if (ev->message_type == ECORE_X_ATOM_NET_DESKTOP_VIEWPORT) { DeskCurrentGotoArea(ev->data.l[0] / WinGetW(VROOT), ev->data.l[1] / WinGetH(VROOT)); return 1; } if (ev->message_type == ECORE_X_ATOM_NET_SHOWING_DESKTOP) { EwinsShowDesktop(ev->data.l[0]); return 1; } #if 0 /* These messages are sent to dedicated window */ if (ev->message_type == ECORE_X_ATOM_NET_STARTUP_INFO_BEGIN) { Eprintf("ECORE_X_ATOM_NET_STARTUP_INFO_BEGIN: %lx: %s\n", ev->window, (char *)ev->data.l); return 1; } if (ev->message_type == ECORE_X_ATOM_NET_STARTUP_INFO) { Eprintf("ECORE_X_ATOM_NET_STARTUP_INFO : %lx: %s\n", ev->window, (char *)ev->data.l); return 1; } #endif #if 0 /* Obsolete? */ EWin *ewin; ewin = EwinFindByClient(ev->window); if (ewin == NULL) { /* Some misbehaving clients go here */ if (ev->message_type == ECORE_X_ATOM_NET_WM_DESKTOP) { ecore_x_netwm_desktop_set(ev->window, ev->data.l[0]); return 1; } else if (ev->message_type == ECORE_X_ATOM_NET_WM_STATE) { ecore_x_window_prop_atom_list_change(ev->window, ECORE_X_ATOM_NET_WM_STATE, ev->data.l[1], ev->data.l[0]); if (ev->data.l[2] == (long)ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ || ev->data.l[2] == (long)ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT) ecore_x_window_prop_atom_list_change(ev->window, ECORE_X_ATOM_NET_WM_STATE, ev->data.l[2], ev->data.l[0]); return 1; } } #endif return 0; }