/* * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors * Copyright (C) 2004-2014 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. */ #include "E.h" #include "aclass.h" #include "animation.h" #include "backgrounds.h" #include "buttons.h" #include "desktops.h" #include "dialog.h" #include "ecompmgr.h" #include "emodule.h" #include "eobj.h" #include "events.h" #include "ewins.h" #include "focus.h" #include "grabs.h" #include "hints.h" #include "iclass.h" #include "screen.h" #include "settings.h" #include "slide.h" #include "timers.h" #include "tooltips.h" #include "xwin.h" #include #if USE_XRANDR #include #endif #define DESK_EVENT_MASK1 \ (ButtonPressMask | ButtonReleaseMask) #define DESK_EVENT_MASK2 \ (EnterWindowMask | LeaveWindowMask | \ SubstructureNotifyMask | SubstructureRedirectMask | PropertyChangeMask) #define DESK_EVENT_MASK (DESK_EVENT_MASK1 | DESK_EVENT_MASK2) #define ENLIGHTENMENT_CONF_NUM_DESKTOPS 32 typedef struct { Desk *current; Desk *previous; Desk *desk[ENLIGHTENMENT_CONF_NUM_DESKTOPS]; unsigned int order[ENLIGHTENMENT_CONF_NUM_DESKTOPS]; int drag_x0, drag_y0; unsigned int prev_num; Animator *anim_slide; } Desktops; static void DeskRaise(unsigned int num); static void DeskLower(unsigned int num); static void DeskHandleEvents(Win win, XEvent * ev, void *prm); static void DeskButtonCallback(void *prm, XEvent * ev, ActionClass * ac); /* The desktops */ static Desktops desks; #define _DeskGet(d) (desks.desk[d]) static void DeskControlsCreate(Desk * dsk) { char s[512]; const char *ic1, *ic2, *ic3; #if ENABLE_DESKRAY const char *ic4; #endif char ac1[64], ac2[64], ac3[64]; Button *b; ActionClass *ac; Action *a; int x[3], y[3], w[3], h[3], m, n, o; const char *t; if (Conf.desks.dragdir < 0 || Conf.desks.dragdir > 3) Conf.desks.dragdir = 2; if (Conf.desks.dragbar_ordering < 0 || Conf.desks.dragbar_ordering > 5) Conf.desks.dragbar_ordering = 1; if (Conf.desks.dragbar_width < 0) Conf.desks.dragbar_width = 0; else if (Conf.desks.dragbar_width > 64) Conf.desks.dragbar_width = 64; if (Conf.desks.dragbar_length < 0) Conf.desks.dragbar_length = 0; else if (Conf.desks.dragbar_length > WinGetW(VROOT)) Conf.desks.dragbar_length = WinGetW(VROOT); Esnprintf(ac1, sizeof(ac1), "DRAGBAR_DESKTOP_%i", dsk->num); if (!ActionclassFind(ac1)) { ac = ActionclassCreate(ac1, 0); a = ActionCreate(EVENT_MOUSE_DOWN, 0, 0, 0, 1, 0, NULL, NULL); ActionclassAddAction(ac, a); Esnprintf(s, sizeof(s), "desk drag %i", dsk->num); ActionAddTo(a, s); a = ActionCreate(EVENT_MOUSE_DOWN, 0, 0, 0, 3, 0, NULL, NULL); ActionclassAddAction(ac, a); ActionAddTo(a, "menus show deskmenu"); a = ActionCreate(EVENT_MOUSE_DOWN, 0, 0, 0, 2, 0, NULL, NULL); ActionclassAddAction(ac, a); ActionAddTo(a, "menus show windowlist"); if (dsk->num > 0) { t = _("Hold down the mouse button and drag\n" "the mouse to be able to drag the desktop\n" "back and forth.\n" "Click right mouse button for a list of all\n" "Desktops and their applications.\n" "Click middle mouse button for a list of all\n" "applications currently running.\n"); ActionclassSetTooltipString(ac, t); } else { t = _("This is the Root desktop.\n" "You cannot drag the root desktop around.\n" "Click right mouse button for a list of all\n" "Desktops and their applications.\n" "Click middle mouse button for a list of all\n" "applications currently running.\n"); ActionclassSetTooltipString(ac, t); } } Esnprintf(ac2, sizeof(ac2), "RAISEBUTTON_DESKTOP_%i", dsk->num); if (!ActionclassFind(ac2)) { ac = ActionclassCreate(ac2, 0); a = ActionCreate(EVENT_MOUSE_UP, 1, 0, 1, 0, 0, NULL, NULL); ActionclassAddAction(ac, a); ActionAddTo(a, "desk next"); t = _("Click here to raise this desktop\nto the top."); ActionclassSetTooltipString(ac, t); } Esnprintf(ac3, sizeof(ac3), "LOWERBUTTON_DESKTOP_%i", dsk->num); if (!ActionclassFind(ac3)) { ac = ActionclassCreate(ac3, 0); a = ActionCreate(EVENT_MOUSE_UP, 1, 0, 1, 0, 0, NULL, NULL); ActionclassAddAction(ac, a); ActionAddTo(a, "desk prev"); t = _("Click here to lower this desktop\nto the bottom."); ActionclassSetTooltipString(ac, t); } if (Conf.desks.dragdir < 2) { ic1 = "DESKTOP_DRAGBUTTON_VERT"; ic2 = "DESKTOP_RAISEBUTTON_VERT"; ic3 = "DESKTOP_LOWERBUTTON_VERT"; #if ENABLE_DESKRAY ic4 = "DESKTOP_DESKRAY_VERT"; #endif } else { ic1 = "DESKTOP_DRAGBUTTON_HORIZ"; ic2 = "DESKTOP_RAISEBUTTON_HORIZ"; ic3 = "DESKTOP_LOWERBUTTON_HORIZ"; #if ENABLE_DESKRAY ic4 = "DESKTOP_DESKRAY_HORIZ"; #endif } switch (Conf.desks.dragbar_ordering) { case 0: m = 0; n = 1; o = 2; break; case 1: m = 0; n = 2; o = 1; break; case 2: m = 2; n = 0; o = 1; break; case 3: m = 1; n = 0; o = 2; break; case 4: m = 1; n = 2; o = 0; break; case 5: m = 2; n = 1; o = 0; break; default: m = 0; n = 1; o = 2; break; } switch (Conf.desks.dragdir) { default: case 0: w[0] = w[1] = w[2] = h[0] = h[1] = Conf.desks.dragbar_width; if (Conf.desks.dragbar_length == 0) h[2] = WinGetH(VROOT) - (Conf.desks.dragbar_width * 2); else h[2] = Conf.desks.dragbar_length; x[0] = x[1] = x[2] = 0; y[m] = 0; y[n] = y[m] + h[m]; y[o] = y[n] + h[n]; break; case 1: w[0] = w[1] = w[2] = h[0] = h[1] = Conf.desks.dragbar_width; if (Conf.desks.dragbar_length == 0) h[2] = WinGetH(VROOT) - (Conf.desks.dragbar_width * 2); else h[2] = Conf.desks.dragbar_length; x[0] = x[1] = x[2] = WinGetW(VROOT) - Conf.desks.dragbar_width; y[m] = 0; y[n] = y[m] + h[m]; y[o] = y[n] + h[n]; break; case 2: h[0] = h[1] = h[2] = w[0] = w[1] = Conf.desks.dragbar_width; if (Conf.desks.dragbar_length == 0) w[2] = WinGetW(VROOT) - (Conf.desks.dragbar_width * 2); else w[2] = Conf.desks.dragbar_length; y[0] = y[1] = y[2] = 0; x[m] = 0; x[n] = x[m] + w[m]; x[o] = x[n] + w[n]; break; case 3: h[0] = h[1] = h[2] = w[0] = w[1] = Conf.desks.dragbar_width; if (Conf.desks.dragbar_length == 0) w[2] = WinGetW(VROOT) - (Conf.desks.dragbar_width * 2); else w[2] = Conf.desks.dragbar_length; y[0] = y[1] = y[2] = WinGetH(VROOT) - Conf.desks.dragbar_width; x[m] = 0; x[n] = x[m] + w[m]; x[o] = x[n] + w[n]; break; } b = NULL; if (Conf.desks.dragbar_width > 0) { ButtonCreate("_DESKTOP_DRAG_CONTROL", 1, ic2, ac2, NULL, NULL, -1, FLAG_FIXED, 1, 99999, 1, 99999, 0, 0, x[0], 0, y[0], 0, 0, w[0], 0, h[0], 0, dsk->num, 0); ButtonCreate("_DESKTOP_DRAG_CONTROL", 1, ic3, ac3, NULL, NULL, -1, FLAG_FIXED, 1, 99999, 1, 99999, 0, 0, x[1], 0, y[1], 0, 0, w[1], 0, h[1], 0, dsk->num, 0); b = ButtonCreate("_DESKTOP_DRAG_CONTROL", 1, ic1, ac1, NULL, NULL, -1, FLAG_FIXED, 1, 99999, 1, 99999, 0, 0, x[2], 0, y[2], 0, 0, w[2], 0, h[2], 0, dsk->num, 0); ButtonSetCallback(b, DeskButtonCallback, dsk); } #if ENABLE_DESKRAY if (dsk->num > 0) { if (Conf.desks.dragdir == 0) { b = ButtonCreate("_DESKTOP_DESKRAY_DRAG_CONTROL", 2, ic4, ac1, NULL, NULL, 1, FLAG_FIXED_VERT, 1, 99999, 1, 99999, 0, 0, EoGetX(dsk), 0, EoGetY(dsk), 0, 0, 0, 0, 0, 1, 0, 1); } else if (Conf.desks.dragdir == 1) { b = ButtonCreate("_DESKTOP_DESKRAY_DRAG_CONTROL", 2, ic4, ac1, NULL, NULL, 1, FLAG_FIXED_VERT, 1, 99999, 1, 99999, 0, 0, EoGetX(dsk) + WinGetW(VROOT) - Conf.desks.dragbar_width, 0, EoGetY(dsk), 0, 0, 0, 0, 0, 1, 0, 1); } else if (Conf.desks.dragdir == 2) { b = ButtonCreate("_DESKTOP_DESKRAY_DRAG_CONTROL", 2, ic4, ac1, NULL, NULL, 1, FLAG_FIXED_HORIZ, 1, 99999, 1, 99999, 0, 0, EoGetX(dsk), 0, EoGetY(dsk), 0, 0, 0, 0, 0, 1, 0, 1); } else { b = ButtonCreate("_DESKTOP_DESKRAY_DRAG_CONTROL", 2, ic4, ac1, NULL, NULL, 1, FLAG_FIXED_HORIZ, 1, 99999, 1, 99999, 0, 0, EoGetX(dsk), 0, EoGetY(dsk) + WinGetH(VROOT) - Conf.desks.dragbar_width, 0, 0, 0, 0, 0, 1, 0, 1); } } #endif dsk->tag = b; } static void DeskControlsDestroy(Desk * dsk, int id) { ButtonsForeach(id, dsk, ButtonDestroy); } static void DeskControlsShow(Desk * dsk, int id) { ButtonsForeach(id, dsk, ButtonShow); } static void DeskConfigure(Desk * dsk) { Background *bg; DeskControlsCreate(dsk); DeskControlsShow(dsk, 1); bg = BackgroundGetForDesk(dsk->num); DeskBackgroundSet(dsk, bg); dsk->bg.pixel = 0xffffffff; if (dsk->num > 0) { EoMove(dsk, WinGetW(VROOT), 0); EoMap(dsk, 0); } ModulesSignal(ESIGNAL_DESK_ADDED, dsk); } static Desk * DeskCreate(int desk, int configure) { #if USE_COMPOSITE EObj *eo; #endif Desk *dsk; Win win; char buf[64]; if (desk < 0 || desk >= ENLIGHTENMENT_CONF_NUM_DESKTOPS) return NULL; dsk = ECALLOC(Desk, 1); if (!dsk) return dsk; desks.desk[desk] = dsk; dsk->num = desk; desks.order[desk] = desk; win = (desk == 0) ? VROOT : NULL; Esnprintf(buf, sizeof(buf), "Desk-%d", desk); EoSetNoRedirect(dsk, 1); EoInit(dsk, EOBJ_TYPE_DESK, win, 0, 0, WinGetW(VROOT), WinGetH(VROOT), 0, buf); EventCallbackRegister(EoGetWin(dsk), DeskHandleEvents, dsk); dsk->bg.o = EoObj(dsk); if (desk == 0) { desks.current = dsk; #if !USE_BG_WIN_ON_ALL_DESKS /* TBD - Use per virtual root bg window? */ #if USE_COMPOSITE /* Add background window */ eo = EobjWindowCreate(EOBJ_TYPE_ROOT_BG, 0, 0, WinGetW(VROOT), WinGetH(VROOT), 0, "Root-bg"); eo->floating = 0; EobjSetLayer(eo, 0); EventCallbackRegister(EobjGetWin(eo), DeskHandleEvents, dsk); dsk->bg.o_bg = eo; ESelectInput(EobjGetWin(eo), EnterWindowMask); #endif #endif } else { EoSetFloating(dsk, 1); EoSetLayer(dsk, 0); /* Set the _XROOT... atoms so apps will find them even before the bg is set */ HintsSetRootInfo(EoGetWin(dsk), NoXID, 0); } #if USE_BG_WIN_ON_ALL_DESKS /* TBD - Use per virtual root bg window? */ #if USE_COMPOSITE /* Add background window */ Esnprintf(buf, sizeof(buf), "Desk-bg-%d", desk); eo = EobjWindowCreate(EOBJ_TYPE_MISC, 0, 0, WinGetW(VROOT), WinGetH(VROOT), 0, buf); eo->floating = 0; EobjReparent(eo, EoObj(dsk), 0, 0); EobjSetLayer(eo, 0); dsk->bg.o_bg = eo; EventCallbackRegister(EobjGetWin(eo), DeskHandleEvents, dsk); #endif #endif HintsSetRootHints(EoGetWin(dsk)); if (configure) DeskConfigure(dsk); /* Root window: Don't include ButtonPressMask as it may cause the event * selection to fail for the other events too. * The ButtonPress/ReleaseMask events are selected in SetupX(). */ if (desk == 0) ESelectInputChange(EoGetWin(dsk), DESK_EVENT_MASK2, 0); else ESelectInput(EoGetWin(dsk), DESK_EVENT_MASK); return dsk; } static void DeskDestroy(Desk * dsk) { ModulesSignal(ESIGNAL_DESK_REMOVED, dsk); #if USE_COMPOSITE if (dsk->bg.o_bg) { EventCallbackUnregister(EobjGetWin(dsk->bg.o_bg), DeskHandleEvents, dsk); EobjWindowDestroy(dsk->bg.o_bg); } #endif EventCallbackUnregister(EoGetWin(dsk), DeskHandleEvents, dsk); DeskControlsDestroy(dsk, 1); DeskControlsDestroy(dsk, 2); if (dsk->bg.bg) BackgroundDecRefcount(dsk->bg.bg); EoFini(dsk); desks.desk[dsk->num] = NULL; Efree(dsk); } EObj * DeskGetBackgroundObj(const Desk * dsk) { return (dsk) ? dsk->bg.o : NULL; } EX_Pixmap DeskGetBackgroundPixmap(const Desk * dsk) { if (!dsk) return NoXID; return dsk->bg.pmap; } Background * DeskBackgroundGet(const Desk * dsk) { return (dsk) ? dsk->bg.bg : NULL; } static void DeskBackgroundConfigure(Desk * dsk) { Win win; EX_Pixmap pmap = dsk->bg.pmap; unsigned int pixel = dsk->bg.pixel; if (EDebug(EDBUG_TYPE_DESKS)) Eprintf ("DeskBackgroundConfigure %d v=%d %#x/%#x: ext=%d pmap=%#x/%#x pixel=%#x/%#x\n", dsk->num, dsk->viewable, EoGetXwin(dsk), EobjGetXwin(dsk->bg.o), BackgroundIsNone(dsk->bg.bg), pmap, dsk->bg.pmap_set, pixel, dsk->bg.pixel); #if USE_COMPOSITE if (dsk->bg.o_bg) { if (ECompMgrIsActive()) { dsk->bg.o = dsk->bg.o_bg; EobjMap(dsk->bg.o_bg, 0); } else { dsk->bg.o = EoObj(dsk); EobjUnmap(dsk->bg.o_bg); } } #endif win = EobjGetWin(dsk->bg.o); if (dsk->viewable || !dsk->bg.bg) { #if USE_COMPOSITE && !USE_BG_WIN_ON_ALL_DESKS if (ECompMgrIsActive()) { ECompMgrDeskConfigure(dsk); ESetWindowBackgroundPixmap(win, NoXID, 0); } else #endif { if (pmap != NoXID) { ESetWindowBackgroundPixmap(win, pmap, 1); if (dsk->num == 0 && win != VROOT) ESetWindowBackgroundPixmap(VROOT, pmap, 1); } else { ESetWindowBackground(win, pixel); if (dsk->num == 0 && win != VROOT) ESetWindowBackground(VROOT, pixel); } EClearWindow(win); } HintsSetRootInfo(EoGetWin(dsk), pmap, pixel); } else if (dsk->bg.bg) { if (!Conf.hints.set_xroot_info_on_root_window) HintsSetRootInfo(EoGetWin(dsk), NoXID, 0); ESetWindowBackgroundPixmap(win, NoXID, 0); if (dsk->num == 0 && win != VROOT) ESetWindowBackgroundPixmap(VROOT, NoXID, 0); } } static void DeskBackgroundRefresh(Desk * dsk, int why) { Background *bg = dsk->bg.bg; EX_Pixmap pmap = dsk->bg.pmap; unsigned int pixel = dsk->bg.pixel; int changed = 0; int reconfigure = 0; if (EDebug(EDBUG_TYPE_DESKS)) Eprintf("DeskBackgroundRefresh %d v=%d why=%d pmap=%#x pixel=%#x\n", dsk->num, dsk->viewable, why, pmap, pixel); switch (why) { case DESK_BG_REFRESH: if (bg && dsk->viewable) BackgroundTouch(bg); break; case DESK_BG_RECONFIGURE_ALL: reconfigure = 1; break; case DESK_BG_TIMEOUT: if (bg && dsk->viewable) BackgroundTouch(bg); return; case DESK_BG_FREE: if (!bg || dsk->viewable) return; break; } if (bg) { if (dsk->viewable) { if (BackgroundGetSeqNo(bg) == dsk->bg.seq_no) goto done; pmap = BackgroundGetPixmap(bg); pixel = 0; if (pmap == NoXID) BackgroundRealize(bg, EoGetWin(dsk), NoXID, EoGetW(dsk), EoGetH(dsk), 1, &pmap, &pixel); if (pmap != NoXID) BackgroundPixmapSet(bg, pmap); dsk->bg.seq_no = BackgroundGetSeqNo(bg); changed = 1; } else { if (dsk->bg.pmap == NoXID) return; pmap = NoXID; pixel = 0; dsk->bg.seq_no = 0; } } else { pmap = (Mode.root.ext_pmap_valid) ? Mode.root.ext_pmap : NoXID; pixel = 0; changed = pmap != dsk->bg.pmap_set; } done: dsk->bg.pmap = pmap; if (reconfigure || pmap != dsk->bg.pmap_set || pixel != dsk->bg.pixel) { dsk->bg.pixel = pixel; DeskBackgroundConfigure(dsk); dsk->bg.pmap_set = pmap; } if (bg && dsk->viewable) if (Conf.hints.set_xroot_info_on_root_window) HintsSetRootInfo(VROOT, pmap, pixel); if (changed) ModulesSignal(ESIGNAL_BACKGROUND_CHANGE, dsk); } void DeskBackgroundSet(Desk * dsk, Background * bg) { if (!dsk) return; BackgroundSetForDesk(bg, dsk->num); if (bg && BackgroundIsNone(bg)) bg = NULL; if (dsk->bg.bg != bg) { if (dsk->bg.bg) BackgroundDecRefcount(dsk->bg.bg); if (bg) BackgroundIncRefcount(bg); } dsk->bg.bg = bg; DeskBackgroundRefresh(dsk, DESK_BG_REFRESH); } void DesksBackgroundRefresh(Background * bg, int why) { Desk *dsk; unsigned int i; for (i = 0; i < Conf.desks.num; i++) { dsk = _DeskGet(i); if (!dsk) /* May happen during init */ continue; if (bg && dsk->bg.bg != bg) continue; DeskBackgroundRefresh(dsk, why); } } static void DeskResize(int desk, int w, int h) { Desk *dsk; int x; dsk = _DeskGet(desk); if (dsk->num != 0) { x = (dsk->viewable) ? EoGetX(dsk) : WinGetW(VROOT); EoMoveResize(dsk, x, 0, w, h); } #if USE_COMPOSITE if (dsk->bg.o_bg) EobjMoveResize(dsk->bg.o_bg, 0, 0, w, h); #endif DeskBackgroundRefresh(dsk, DESK_BG_REFRESH); DeskControlsDestroy(dsk, 1); DeskControlsCreate(dsk); DeskControlsShow(dsk, 1); } Desk * DeskGet(unsigned int desk) { if (desk >= Conf.desks.num) return NULL; return _DeskGet(desk); } Desk * DeskGetValid(unsigned int desk) { if (desk >= Conf.desks.num) desk = 0; return _DeskGet(desk); } Desk * DeskGetRelative(Desk * dsk, int inc) { unsigned int desk, num; num = Conf.desks.num; desk = (dsk) ? dsk->num : 0; inc %= (int)num; desk += num + inc; desk %= num; return _DeskGet(desk); } void DeskGetArea(const Desk * dsk, int *ax, int *ay) { if (!dsk) { *ax = *ay = 0; return; } *ax = dsk->current_area_x; *ay = dsk->current_area_y; } void DeskSetArea(Desk * dsk, int ax, int ay) { if (!dsk) return; dsk->current_area_x = ax; dsk->current_area_y = ay; } void DeskSetDirtyStack(Desk * dsk, EObj * eo) { dsk->stack.dirty++; dsk->stack.latest = eo; if (EobjGetType(eo) == EOBJ_TYPE_EWIN) dsk->stack.update_client_list = 1; if (EDebug(EDBUG_TYPE_STACKING)) Eprintf("DeskSetDirtyStack %d (%d): %s\n", dsk->num, dsk->stack.dirty, EobjGetName(eo)); } void DeskCurrentGetArea(int *ax, int *ay) { DeskGetArea(desks.current, ax, ay); } static void DeskCurrentSetArea(int ax, int ay) { DeskSetArea(desks.current, ax, ay); } unsigned int DesksGetNumber(void) { return Conf.desks.num; } Desk * DesksGetCurrent(void) { return desks.current; } unsigned int DesksGetCurrentNum(void) { return desks.current->num; } void DesksSetCurrent(Desk * dsk) { if (!dsk) return; desks.current = dsk; } static void DesksResize(int w, int h) { unsigned int i; BackgroundsInvalidate(0); for (i = 0; i < Conf.desks.num; i++) DeskResize(i, w, h); EdgeWindowsShow(); ModulesSignal(ESIGNAL_DESK_RESIZE, NULL); } static void ChangeNumberOfDesktops(unsigned int quantity) { unsigned int i; int j, num; EWin *const *lst; if (quantity >= ENLIGHTENMENT_CONF_NUM_DESKTOPS) quantity = ENLIGHTENMENT_CONF_NUM_DESKTOPS; if (quantity <= 0 || quantity == Conf.desks.num) return; for (i = quantity; i < Conf.desks.num; i++) DeskLower(i); if (quantity > Conf.desks.num) { while (Conf.desks.num < quantity) { Conf.desks.num++; DeskCreate(Conf.desks.num - 1, 1); } } else if (quantity < Conf.desks.num) { lst = EwinListGetAll(&num); for (j = 0; j < num; j++) { if (EoGetDeskNum(lst[j]) >= quantity) EwinMoveToDesktop(lst[j], _DeskGet(0)); } while (Conf.desks.num > quantity) { DeskDestroy(_DeskGet(Conf.desks.num - 1)); Conf.desks.num--; } } if (DesksGetCurrentNum() >= Conf.desks.num) DeskGotoNum(Conf.desks.num - 1); HintsSetDesktopConfig(); autosave(); } static void DesksControlsCreate(void) { unsigned int i; for (i = 0; i < Conf.desks.num; i++) DeskControlsCreate(_DeskGet(i)); } static void DesksControlsDestroy(void) { unsigned int i; for (i = 0; i < Conf.desks.num; i++) DeskControlsDestroy(_DeskGet(i), 1); } static void DesksControlsShow(void) { unsigned int i; for (i = 0; i < Conf.desks.num; i++) DeskControlsShow(_DeskGet(i), 1); } static void DesksControlsRefresh(void) { DesksControlsDestroy(); DesksControlsCreate(); DesksControlsShow(); autosave(); } #if 0 /* Unused */ static void DeskShowTabs(void) { ButtonsForeach(2, NULL, ButtonShow); } static void DeskHideTabs(void) { ButtonsForeach(2, NULL, ButtonHide); } #endif static void DeskButtonShowDefault(Button * b) { if (!ButtonDoShowDefault(b)) return; ButtonShow(b); } static void DeskShowButtons(void) { ButtonsForeach(0, NULL, DeskButtonShowDefault); } static void MoveToDeskTop(Desk * dsk) { int i, j; EoRaise(dsk); j = -1; i = 0; while (j < 0 && i < (int)Conf.desks.num) { if (desks.order[i] == dsk->num) j = i; i++; } if (j < 0) return; if (j > 0) { for (i = j - 1; i >= 0; i--) desks.order[i + 1] = desks.order[i]; desks.order[0] = dsk->num; } } static void MoveToDeskBottom(Desk * dsk) { int i, j; EoLower(dsk); j = -1; i = 0; while (j < 0 && i < (int)Conf.desks.num) { if (desks.order[i] == dsk->num) j = i; i++; } if (j < 0) return; if (j < (int)Conf.desks.num - 1) { for (i = j; i < (int)Conf.desks.num - 1; i++) desks.order[i] = desks.order[i + 1]; desks.order[Conf.desks.num - 1] = dsk->num; } } Desk * DesktopAt(int x, int y) { Desk *dsk; unsigned int i; for (i = 0; i < Conf.desks.num; i++) { dsk = _DeskGet(desks.order[i]); if (x >= EoGetX(dsk) && x < (EoGetX(dsk) + WinGetW(VROOT)) && y >= EoGetY(dsk) && y < (EoGetY(dsk) + WinGetH(VROOT))) return _DeskGet(desks.order[i]); } return _DeskGet(0); } static void DesksStackingCheck(void) { Desk *dsk; unsigned int i; for (i = 0; i < Conf.desks.num; i++) { dsk = _DeskGet(i); if (i && !dsk->viewable) continue; if (!dsk->stack.dirty) continue; DeskRestack(dsk); } } static void _DesksIdler(void *data __UNUSED__) { DesksStackingCheck(); } static void DeskMove(Desk * dsk, int x, int y) { Desk *dd; unsigned int i; int n, v, dx, dy; if (dsk->num <= 0) return; n = -1; i = 0; while (n < 0 && i < Conf.desks.num) { if (desks.order[i] == dsk->num) n = i; i++; } if (n < 0) /* Should not be possible */ return; dx = x - EoGetX(dsk); dy = y - EoGetY(dsk); if (x == 0 && y == 0) { /* Desks below are obscured - touch and set unviewable */ for (i = n + 1; i < Conf.desks.num; i++) { dd = _DeskGet(desks.order[i]); if (dd->viewable) BackgroundTouch(dd->bg.bg); dd->viewable = 0; } } else { v = dsk->viewable; for (i = n + 1; i < Conf.desks.num; i++) { dd = _DeskGet(desks.order[i]); if (!dd->viewable && v) { dd->viewable = 1; DeskBackgroundRefresh(_DeskGet(desks.order[i]), DESK_BG_REFRESH); } else if (dd->viewable && !v) { BackgroundTouch(dd->bg.bg); dd->viewable = 0; } if (EoGetX(dd) == 0 && EoGetY(dd) == 0) v = 0; } } EoMove(dsk, x, y); if (dsk->tag) ButtonMoveRelative(dsk->tag, dx, dy); #if 0 /* FIXME - Remove? */ EWin *const *lst; lst = EwinListGetAll(&n); for (i = 0; i < (unsigned int)n; i++) if (EoGetDesk(lst[i]) == dsk) ICCCM_Configure(lst[i]); #endif } static void DeskHide(unsigned int desk) { Desk *dsk; if (desk <= 0 || desk >= Conf.desks.num) return; dsk = _DeskGet(desk); if (dsk->viewable) BackgroundTouch(dsk->bg.bg); dsk->viewable = 0; EoMove(dsk, WinGetW(VROOT), 0); } static void DeskEnter(Desk * dsk) { int i; EGrabServer(); dsk->viewable = 1; DeskBackgroundRefresh(dsk, DESK_BG_REFRESH); MoveToDeskTop(dsk); desks.prev_num = desks.current->num; desks.previous = desks.current = dsk; if (dsk->num == 0) { for (i = Conf.desks.num - 1; i > 0; i--) DeskHide(desks.order[i]); } EwinsMoveStickyToDesk(dsk); ButtonsMoveStickyToDesk(dsk); DesksStackingCheck(); EdgeWindowsShow(); EUngrabServer(); } void DeskGotoNum(unsigned int desk) { Desk *dsk; if (Conf.desks.desks_wraparound) desk %= Conf.desks.num; if (desk >= Conf.desks.num || desk == desks.current->num) return; dsk = _DeskGet(desk); DeskGoto(dsk); } static void DeskSwitchStart(void) { FocusNewDeskBegin(); } static void DeskSwitchDone(void) { HintsSetCurrentDesktop(); FocusNewDesk(); } static void _DeskGotoStart(Desk * dsk) { if (EDebug(EDBUG_TYPE_DESKS)) Eprintf("DeskGoto %d\n", dsk->num); ModulesSignal(ESIGNAL_DESK_SWITCH_START, NULL); MoveResizeSuspend(); DeskSwitchStart(); } static void _DeskGotoEnd(Desk * dsk) { DeskSwitchDone(); MoveResizeResume(); ModulesSignal(ESIGNAL_DESK_SWITCH_DONE, NULL); if (EDebug(EDBUG_TYPE_DESKS)) Eprintf("DeskGoto %d done\n", dsk->num); } static int _DeskGotoRun(EObj * eo, int run, void *state) { int *xy = (int *)state; int x, y; Desk *dsk = (Desk *) eo; x = (run * xy[0]) >> 10; y = (run * xy[1]) >> 10; EobjMove(eo, x, y); if (run == 0) { if (xy[2]) DeskEnter(dsk); DeskMove(dsk, 0, 0); _DeskGotoEnd(dsk); EventsBlock(0); } return 0; } void DeskGoto(Desk * dsk) { if (!dsk || dsk == desks.previous) return; _DeskGotoStart(dsk); if (dsk->num > 0) { if (Conf.desks.slidein) { EventsBlock(1); if (!dsk->viewable) { int x, y; switch (Conf.desks.dragdir) { default: case 0: x = WinGetW(VROOT); y = 0; break; case 1: x = -WinGetW(VROOT); y = 0; break; case 2: x = 0; y = WinGetH(VROOT); break; case 3: x = 0; y = -WinGetH(VROOT); break; } DeskMove(dsk, x, y); int xy[3] = { x, y, 0 }; DeskEnter(dsk); AnimatorAdd(EoObj(dsk), ANIM_SLIDE, _DeskGotoRun, 1000000 / Conf.desks.slidespeed, 0, sizeof(xy), xy); } else { int xy[3] = { EoGetX(dsk), EoGetY(dsk), 1 }; AnimatorAdd(EoObj(dsk), ANIM_SLIDE, _DeskGotoRun, 1000000 / Conf.desks.slidespeed, 0, sizeof(xy), xy); } return; } else { DeskEnter(dsk); } DeskMove(dsk, 0, 0); } else { DeskEnter(dsk); } _DeskGotoEnd(dsk); } static void UncoverDesktop(unsigned int desk) { Desk *dsk; if (desk >= Conf.desks.num) return; dsk = _DeskGet(desk); dsk->viewable = 1; DeskBackgroundRefresh(dsk, DESK_BG_REFRESH); } static void DeskRaise(unsigned int desk) { Desk *dsk; if (desk >= Conf.desks.num) return; dsk = _DeskGet(desk); if (EDebug(EDBUG_TYPE_DESKS)) Eprintf("DeskRaise(%d) current=%d\n", desk, desks.current->num); DeskSwitchStart(); DeskEnter(dsk); DeskSwitchDone(); ModulesSignal(ESIGNAL_DESK_SWITCH_DONE, NULL); ESync(ESYNC_DESKS); } static void DeskLower(unsigned int desk) { Desk *dsk; if ((desk <= 0) || (desk >= Conf.desks.num)) return; dsk = _DeskGet(desk); DeskSwitchStart(); MoveToDeskBottom(dsk); if (EDebug(EDBUG_TYPE_DESKS)) Eprintf("DeskLower(%d) %d -> %d\n", desk, desks.current->num, desks.order[0]); desks.previous = desks.current = DeskGet(desks.order[0]); EGrabServer(); UncoverDesktop(desks.order[0]); DeskHide(desk); EwinsMoveStickyToDesk(desks.current); ButtonsMoveStickyToDesk(desks.current); DesksStackingCheck(); DeskSwitchDone(); if (Mode.mode == MODE_NONE) ModulesSignal(ESIGNAL_DESK_SWITCH_DONE, NULL); EUngrabServer(); ESync(ESYNC_DESKS); } #if 0 /* Unused */ void DeskShow(int desk) { Desk *dsk; int i; if (desk < 0 || desk >= Conf.desks.num) return; dsk = _DeskGet(desk); dsk->viewable = 1; DeskBackgroundRefresh(dsk, DESK_BG_REFRESH); MoveToDeskTop(desk); if (desk == 0) { for (i = Conf.desks.num - 1; i > 0; i--) DeskHide(desks.order[i]); } } #endif static void DeskRestackSimple(Desk * dsk) { EObj *const *lst, *eo; int i, num; XWindowChanges xwc; unsigned int value_mask; eo = dsk->stack.latest; lst = EobjListStackGetForDesk(&num, dsk); if (num < 2) return; for (i = 0; i < num; i++) if (lst[i] == eo) break; if (i >= num) return; eo->stacked = 1; if (EDebug(EDBUG_TYPE_STACKING)) Eprintf("DeskRestackSimple %#x %s\n", EobjGetXwin(eo), EobjGetName(eo)); if (i < num - 1) { xwc.stack_mode = Above; xwc.sibling = EobjGetXwin(lst[i + 1]); } else { xwc.stack_mode = Below; xwc.sibling = EobjGetXwin(lst[i - 1]); } value_mask = CWSibling | CWStackMode; if (EDebug(EDBUG_TYPE_STACKING)) Eprintf("DeskRestackSimple %#10x %s %#10lx\n", EobjGetXwin(eo), (xwc.stack_mode == Above) ? "Above" : "Below", xwc.sibling); XConfigureWindow(disp, EobjGetXwin(eo), value_mask, &xwc); } #define _APPEND_TO_WIN_LIST(win) \ { \ wl = EREALLOC(EX_Window, wl, ++tot); \ wl[tot - 1] = win; \ } void DeskRestack(Desk * dsk) { EX_Window *wl; int i, num, tot; EObj *const *lst, *eo; if (!dsk->stack.dirty) return; /* Special case if only one window needs restacking */ if (dsk->stack.dirty == 1) { DeskRestackSimple(dsk); goto done; } /* Build the window stack, top to bottom */ tot = 0; wl = NULL; lst = EobjListStackGetForDesk(&num, dsk); /* Normal objects */ for (i = 0; i < num; i++) { eo = lst[i]; _APPEND_TO_WIN_LIST(EobjGetXwin(eo)); eo->stacked = 1; } if (EDebug(EDBUG_TYPE_STACKING)) { Eprintf("DeskRestack %d (%d):\n", dsk->num, dsk->stack.dirty); for (i = 0; i < tot; i++) Eprintf(" win=%#10x parent=%#10x\n", wl[i], EXWindowGetParent(wl[i])); } EXRestackWindows(wl, tot); Efree(wl); done: if (dsk->stack.update_client_list) { dsk->stack.update_client_list = 0; HintsSetClientStacking(); ClickGrabsUpdate(); } dsk->stack.dirty = 0; dsk->stack.latest = NULL; } void DeskGotoByEwin(EWin * ewin) { if (EoIsSticky(ewin) || EoIsFloating(ewin)) return; DeskGoto(EoGetDesk(ewin)); DeskCurrentGotoArea(ewin->area_x, ewin->area_y); } /* * Areas */ void DesksFixArea(int *ax, int *ay) { if (*ax < 0) { if (Conf.desks.areas_wraparound) *ax = Conf.desks.areas_nx - 1; else *ax = 0; } else if (*ax >= Conf.desks.areas_nx) { if (Conf.desks.areas_wraparound) *ax = 0; else *ax = Conf.desks.areas_nx - 1; } if (*ay < 0) { if (Conf.desks.areas_wraparound) *ay = Conf.desks.areas_ny - 1; else *ay = 0; } else if (*ay >= Conf.desks.areas_ny) { if (Conf.desks.areas_wraparound) *ay = 0; else *ay = Conf.desks.areas_ny - 1; } } static int AreaXYToLinear(int ax, int ay) { DesksFixArea(&ax, &ay); return (ay * Conf.desks.areas_nx) + ax; } static void AreaLinearToXY(int a, int *ax, int *ay) { if (a < 0) a = 0; else if (a >= (Conf.desks.areas_nx * Conf.desks.areas_ny)) a = (Conf.desks.areas_nx * Conf.desks.areas_ny) - 1; *ay = a / Conf.desks.areas_nx; *ax = a - (*ay * Conf.desks.areas_nx); } static void SetAreaSize(int aw, int ah) { if (aw < 1) aw = 1; if (ah < 1) ah = 1; Conf.desks.areas_nx = aw; Conf.desks.areas_ny = ah; HintsSetViewportConfig(); EdgeWindowsShow(); ModulesSignal(ESIGNAL_AREA_CONFIGURED, NULL); } void DesksGetAreaSize(int *aw, int *ah) { *aw = Conf.desks.areas_nx; *ah = Conf.desks.areas_ny; } static void SetNewAreaSize(int ax, int ay) { int a, b, i, num; EWin *const *lst; if (ax <= 0) return; if (ay <= 0) return; DesksGetAreaSize(&a, &b); if ((a == ax) && (b == ay)) return; SetAreaSize(ax, ay); lst = EwinListGetAll(&num); for (i = 0; i < num; i++) { if (!EoIsSticky(lst[i])) { if (lst[i]->area_x >= ax) EwinMoveToArea(lst[i], ax - 1, lst[i]->area_x); if (lst[i]->area_y >= ay) EwinMoveToArea(lst[i], lst[i]->area_x, ay - 1); } } DeskCurrentGetArea(&a, &b); if (a >= ax) { DeskCurrentGotoArea(ax - 1, b); DeskCurrentGetArea(&a, &b); } if (b >= ay) DeskCurrentGotoArea(a, ay - 1); autosave(); } static void SetCurrentLinearArea(int a) { int ax, ay; AreaLinearToXY(a, &ax, &ay); DeskCurrentGotoArea(ax, ay); } static int GetCurrentLinearArea(void) { int ax, ay; DeskCurrentGetArea(&ax, &ay); return AreaXYToLinear(ax, ay); } static void MoveCurrentLinearAreaBy(int a) { SetCurrentLinearArea(GetCurrentLinearArea() + a); } /* Return 1 to disable area switch */ static int _DeskAreaSwitchCheckEwins(void) { EWin *const *lst, *ewin; int i, num; lst = EwinListGetForDesk(&num, desks.current); for (i = 0; i < num; i++) { ewin = lst[i]; /* Disable if there are non-sticky shading windows */ if (EoIsSticky(ewin) || ewin->state.iconified) continue; if (ewin->state.shading) return 1; } return 0; } static void DeskAreaSwitchStart(void) { FocusNewDeskBegin(); } static void DeskAreaSwitchDone(void) { HintsSetDesktopViewport(); FocusNewDesk(); } static void _DeskCurrentGotoAreaStart(int pax, int pay, int ax, int ay) { if (EDebug(EDBUG_TYPE_DESKS)) Eprintf("DeskCurrentGotoArea %d,%d\n", ax, ay); ModulesSignal(ESIGNAL_AREA_SWITCH_START, NULL); if (ax < pax) SoundPlay(SOUND_MOVE_AREA_LEFT); else if (ax > pax) SoundPlay(SOUND_MOVE_AREA_RIGHT); else if (ay < pay) SoundPlay(SOUND_MOVE_AREA_UP); else if (ay > pay) SoundPlay(SOUND_MOVE_AREA_DOWN); MoveResizeSuspend(); DeskAreaSwitchStart(); /* set the current area up in out data structs */ DeskCurrentSetArea(ax, ay); } typedef struct { EWin *const *ewins_desk; EWin **ewins_slide; int n_ewins_desk, n_ewins_slide; int slide_dx, slide_dy; } slide_area_data_t; static void _DeskCurrentGotoAreaEnd(slide_area_data_t * sad) { EWin *const *lst, *ewin; int i, num, dx, dy; desks.anim_slide = NULL; lst = sad->ewins_desk; num = sad->n_ewins_desk; dx = sad->slide_dx; dy = sad->slide_dy; /* move all windows to their final positions */ for (i = 0; i < num; i++) { ewin = lst[i]; if (EwinIsTransientChild(ewin)) continue; if (EoGetDesk(ewin) != DesksGetCurrent() && !EoIsFloating(ewin)) continue; if (EoIsSticky(ewin) || (EoIsFloating(ewin) && Conf.movres.mode_move == MR_OPAQUE) || (!ewin->state.iconified && Conf.desks.slidein)) EwinMove(ewin, EoGetX(ewin), EoGetY(ewin), MRF_NOCHECK_ONSCREEN); else EwinMove(ewin, EoGetX(ewin) - dx, EoGetY(ewin) - dy, MRF_NOCHECK_ONSCREEN); } Efree(sad->ewins_slide); if (!Conf.desks.slidein) EobjsRepaint(); MoveResizeResume(); /* re-focus on a new ewin on that new desktop area */ DeskAreaSwitchDone(); if (EDebug(EDBUG_TYPE_DESKS)) Eprintf("%s done\n", __func__); ModulesSignal(ESIGNAL_AREA_SWITCH_DONE, DesksGetCurrent()); /* update which "edge flip resistance" detector windows are visible */ EdgeWindowsShow(); } static int _DeskCurrentGotoAreaRun(EObj * eo __UNUSED__, int run, void *state) { slide_area_data_t *sad = (slide_area_data_t *) state; EWin *ewin; int i, dx, dy; dx = (run * sad->slide_dx) >> 10; dy = (run * sad->slide_dy) >> 10; for (i = 0; i < sad->n_ewins_slide; i++) { ewin = sad->ewins_slide[i]; EoMove(ewin, ewin->trg_x + dx, ewin->trg_y + dy); } if (run == 0) { _DeskCurrentGotoAreaEnd(sad); EventsBlock(0); } return 0; } void DeskCurrentGotoArea(int ax, int ay) { slide_area_data_t _sad, *sad = &_sad; EWin *const *lst, *ewin; int i, num, dx, dy, pax, pay; if (desks.anim_slide) return; if ((Mode.mode == MODE_RESIZE) || (Mode.mode == MODE_RESIZE_H) || (Mode.mode == MODE_RESIZE_V)) return; if (_DeskAreaSwitchCheckEwins()) return; DesksFixArea(&ax, &ay); DeskCurrentGetArea(&pax, &pay); if (ax == pax && ay == pay) return; _DeskCurrentGotoAreaStart(pax, pay, ax, ay); /* move all the windows around */ dx = WinGetW(VROOT) * (ax - pax); dy = WinGetH(VROOT) * (ay - pay); lst = EwinListGetAll(&num); sad->ewins_desk = lst; sad->n_ewins_desk = num; sad->ewins_slide = NULL; sad->n_ewins_slide = 0; sad->slide_dx = dx; sad->slide_dy = dy; if (Conf.desks.slidein && Conf.desks.slidespeed > 10) { int wnum = 0; EWin **wl = NULL; /* create the list of windwos to move */ for (i = 0; i < num; i++) { ewin = lst[i]; if (EoIsSticky(ewin) || ewin->state.iconified) continue; if (EoGetDesk(ewin) != DesksGetCurrent() && !EoIsFloating(ewin)) continue; if (EoIsFloating(ewin) && Conf.movres.mode_move == MR_OPAQUE) continue; wnum++; wl = EREALLOC(EWin *, wl, wnum); wl[wnum - 1] = ewin; ewin->trg_x = EoGetX(ewin) - dx; ewin->trg_y = EoGetY(ewin) - dy; } sad->ewins_slide = wl; sad->n_ewins_slide = wnum; /* slide them */ if (wl) { desks.anim_slide = AnimatorAdd(NULL, ANIM_SLIDE, _DeskCurrentGotoAreaRun, 1000000 / Conf.desks.slidespeed, 0, sizeof(slide_area_data_t), sad); EventsBlock(1); return; } } _DeskCurrentGotoAreaEnd(sad); } void DeskCurrentMoveAreaBy(int dx, int dy) { int ax, ay; DeskCurrentGetArea(&ax, &ay); DeskCurrentGotoArea(ax + dx, ay + dy); } /* * Actions, events */ static char sentpress = 0; static void ButtonProxySendEvent(XEvent * ev) { if (Mode.button_proxy_win) EXSendEvent(Mode.button_proxy_win, SubstructureNotifyMask, ev); } static void DeskDragStart(int desk) { Desk *dsk; dsk = DeskGet(desk); if (!dsk) return; desks.drag_x0 = Mode.events.cx - EoGetX(dsk); desks.drag_y0 = Mode.events.cy - EoGetY(dsk); Mode.mode = MODE_DESKDRAG; } static void DeskDragEnd(Desk * dsk __UNUSED__) { Mode.mode = MODE_NONE; } static void DeskDragMotion(Desk * dsk) { int x, y; x = Mode.events.mx - desks.drag_x0; y = Mode.events.my - desks.drag_y0; switch (Conf.desks.dragdir) { case 0: if (x < 0) x = 0; y = 0; break; case 1: if (x > 0) x = 0; y = 0; break; case 2: x = 0; if (y < 0) y = 0; break; case 3: x = 0; if (y > 0) y = 0; break; default: break; } DeskMove(dsk, x, y); } static void DeskButtonCallback(void *prm, XEvent * ev, ActionClass * ac) { Desk *dsk = (Desk *) prm; if (Mode.mode != MODE_DESKDRAG) { if (ac) ActionclassEvent(ac, ev, NULL); return; } switch (ev->type) { case ButtonRelease: DeskDragEnd(dsk); break; case MotionNotify: DeskDragMotion(dsk); break; } } static int DeskCheckAction(Desk * dsk __UNUSED__, XEvent * ev) { ActionClass *ac; ac = ActionclassFind("DESKBINDINGS"); if (!ac) return 0; return ActionclassEvent(ac, ev, NULL); } static void DeskEventButtonPress(Desk * dsk, XEvent * ev) { /* Don't handle desk bindings while doing stuff */ if (Mode.mode) return; GrabPointerRelease(); if (!DeskCheckAction(dsk, ev)) ButtonProxySendEvent(ev); } static void DeskEventButtonRelease(Desk * dsk, XEvent * ev) { /* Don't handle desk bindings while doing stuff */ if (Mode.mode) return; if (sentpress) { /* We never get here? */ sentpress = 0; ButtonProxySendEvent(ev); } DeskCheckAction(dsk, ev); } static void DeskRootResize(int root, int w, int h) { if (EDebug(EDBUG_TYPE_DESKS)) Eprintf("DeskRootResize %d %dx%d\n", root, w, h); if (root && (VROOT != RROOT)) { WinGetW(RROOT) = w; WinGetH(RROOT) = h; } /* Quit if no change */ if (w == WinGetW(VROOT) && h == WinGetH(VROOT)) return; EWindowSync(VROOT); /* Quit if size is not final */ if (w != WinGetW(VROOT) || h != WinGetH(VROOT)) return; ScreenInit(); DesksResize(w, h); HintsSetDesktopConfig(); Mode.screen.w_old = WinGetW(VROOT); Mode.screen.h_old = WinGetH(VROOT); } static ActionClass * DeskGetAclass(void *data __UNUSED__) { return ActionclassFind("DESKBINDINGS"); } static void DeskPropertyChange(Desk * dsk, XEvent * ev) { EX_Pixmap pmap; if (ev->xproperty.atom == E_XROOTPMAP_ID) { /* Possible race here? */ pmap = HintsGetRootPixmap(EoGetWin(dsk)); if (EDebug(EDBUG_TYPE_DESKS)) Eprintf("DeskPropertyChange win=%#lx _XROOTPMAP_ID=%#x\n", ev->xany.window, pmap); if (ev->xany.window != WinGetXwin(VROOT)) return; if (pmap == dsk->bg.pmap) return; if (pmap == Mode.root.ext_pmap) return; Mode.root.ext_pmap = pmap; Mode.root.ext_pmap_valid = EXDrawableOk(pmap); DesksBackgroundRefresh(NULL, DESK_BG_REFRESH); } else if (ev->xproperty.atom == E_XROOTCOLOR_PIXEL) { if (EDebug(EDBUG_TYPE_DESKS)) Eprintf("DeskPropertyChange win=%#lx _XROOTCOLOR_PIXEL\n", ev->xany.window); if (ev->xany.window != WinGetXwin(VROOT)) return; } } static void DeskHandleEvents(Win win __UNUSED__, XEvent * ev, void *prm) { Desk *dsk = (Desk *) prm; switch (ev->type) { case ButtonPress: DeskEventButtonPress(dsk, ev); break; case ButtonRelease: DeskEventButtonRelease(dsk, ev); break; case EnterNotify: FocusHandleEnter(NULL, ev); break; case LeaveNotify: FocusHandleLeave(NULL, ev); break; case MotionNotify: /* Motion over desk buttons doesn't go here - We probably don't care much. */ DesksSetCurrent(DesktopAt(Mode.events.mx, Mode.events.my)); TooltipsSetPending(1, DeskGetAclass, dsk); break; case ConfigureNotify: if (ev->xconfigure.window != WinGetXwin(VROOT)) break; if (Mode.wm.window) /* This test should not be necessary but... */ { Mode.wm.win_x = ev->xconfigure.x; Mode.wm.win_y = ev->xconfigure.y; } DeskRootResize(0, ev->xconfigure.width, ev->xconfigure.height); break; case PropertyNotify: if (ev->xany.window == WinGetXwin(VROOT)) DeskPropertyChange(dsk, ev); break; #if USE_XRANDR case EX_EVENT_SCREEN_CHANGE_NOTIFY: { XRRScreenChangeNotifyEvent *rrev = (XRRScreenChangeNotifyEvent *) ev; EventsRandrScreenChange(ev); DeskRootResize(1, rrev->width, rrev->height); } break; #endif } } /* Settings */ static void DeskDragdirSet(const char *params) { Desk *dsk; unsigned int i; int pd; pd = Conf.desks.dragdir; if (params && params[0]) Conf.desks.dragdir = atoi(params); else { Conf.desks.dragdir++; if (Conf.desks.dragdir > 3) Conf.desks.dragdir = 0; } if (pd == Conf.desks.dragdir) return; for (i = 1; i < Conf.desks.num; i++) { dsk = _DeskGet(i); EoMove(dsk, (dsk->viewable) ? 0 : WinGetW(VROOT), 0); } DesksControlsRefresh(); } static void DeskDragbarOrderSet(const char *params) { int pd; pd = Conf.desks.dragbar_ordering; if (params && params[0]) Conf.desks.dragbar_ordering = atoi(params); else { Conf.desks.dragbar_ordering++; if (Conf.desks.dragbar_ordering > 5) Conf.desks.dragbar_ordering = 0; } if (pd == Conf.desks.dragbar_ordering) return; DesksControlsRefresh(); } #if 0 /* FIXME */ static int doDragbarWidthSet(EWin * edummy, const char *params) { int pd; Button *b; pd = Conf.desks.dragbar_width; if (params) Conf.desks.dragbar_width = atoi(params); if (pd != Conf.desks.dragbar_width) { DesksControlsRefresh(); } return 0; } static int doDragbarLengthSet(EWin * edummy, const char *params) { int pd; Button *b; pd = Conf.desks.dragbar_length; if (params) Conf.desks.dragbar_length = atoi(params); if (pd != Conf.desks.dragbar_length) { DesksControlsRefresh(); } return 0; } #endif #if ENABLE_DESKRAY static int doDeskray(EWin * edummy, const char *params) { if (params) { if (!atoi(params)) { DeskHideTabs(); Conf.deskmode = MODE_NONE; } else { Conf.deskmode = MODE_DESKRAY; DeskShowTabs(); } } else { if (Conf.deskmode == MODE_DESKRAY) { DeskHideTabs(); Conf.deskmode = MODE_NONE; } else { Conf.deskmode = MODE_DESKRAY; DeskShowTabs(); } } return 0; } #endif /* ENABLE_DESKRAY */ static void DesksInit(void) { unsigned int i; memset(&desks, 0, sizeof(desks)); Mode.screen.w_old = WinGetW(VROOT); Mode.screen.h_old = WinGetH(VROOT); Mode.backgrounds.mini_w = WinGetW(VROOT) / 12; Mode.backgrounds.mini_h = WinGetH(VROOT) / 12; /* Backward compatibility hack */ if (Conf.desks.edge_flip_resistance <= 0) Conf.desks.edge_flip_mode = EDGE_FLIP_OFF; desks.previous = NULL; for (i = 0; i < Conf.desks.num; i++) DeskCreate(i, 0); SetAreaSize(Conf.desks.areas_nx, Conf.desks.areas_ny); /* Retreive stuff from last time we were loaded if we're restarting */ EHintsGetDeskInfo(); HintsSetDesktopConfig(); HintsSetDesktopViewport(); } static void DesksConfigure(void) { unsigned int i; for (i = 0; i < Conf.desks.num; i++) DeskConfigure(_DeskGet(i)); UncoverDesktop(0); } /* * Desktops Module */ static void DesksSighan(int sig, void *prm __UNUSED__) { switch (sig) { case ESIGNAL_INIT: DesksInit(); break; case ESIGNAL_CONFIGURE: DesksConfigure(); break; case ESIGNAL_START: /* Draw all the buttons that belong on the desktop */ DeskShowButtons(); IdlerAdd(_DesksIdler, NULL); break; } } #if ENABLE_DIALOGS /* * Dialogs */ typedef struct { int desktops; int prev_desktops; DItem *desk_text; char desktop_slide; int desktop_slide_speed; char desktop_wraparound; char dragbar; int dragdir; char initialised; Win wins[ENLIGHTENMENT_CONF_NUM_DESKTOPS]; } DeskDlgData; static void CB_ConfigureDesktops(Dialog * d, int val, void *data __UNUSED__) { DeskDlgData *dd = DLG_DATA_GET(d, DeskDlgData); if (val >= 2) return; ChangeNumberOfDesktops(dd->desktops); Conf.desks.slidein = dd->desktop_slide; Conf.desks.slidespeed = dd->desktop_slide_speed; Conf.desks.desks_wraparound = dd->desktop_wraparound; if ((Conf.desks.dragdir != dd->dragdir) || ((dd->dragbar) && (Conf.desks.dragbar_width < 1)) || ((!dd->dragbar) && (Conf.desks.dragbar_width > 0))) { if (dd->dragbar) Conf.desks.dragbar_width = 16; else Conf.desks.dragbar_width = 0; Conf.desks.dragdir = dd->dragdir; DesksControlsRefresh(); } autosave(); } static void CB_DesktopDisplayRedraw(Dialog * d, int val, void *data) { DeskDlgData *dd = DLG_DATA_GET(d, DeskDlgData); DItem *di = (DItem *) data; int i; int w, h; Win win; char s[64]; ImageClass *ic; if ((val != 1) && (dd->prev_desktops == dd->desktops)) return; dd->prev_desktops = dd->desktops; win = DialogItemAreaGetWindow(di); DialogItemAreaGetSize(di, &w, &h); if (!dd->initialised) { ic = ImageclassFind("SETTINGS_DESKTOP_AREA", 1); ImageclassApply(ic, win, 0, 0, STATE_NORMAL, ST_SOLID); dd->initialised = 1; } for (i = 0; i < dd->desktops; i++) { if (!dd->wins[i]) { Background *bg; dd->wins[i] = ECreateWindow(win, 0, 0, Mode.backgrounds.mini_w, Mode.backgrounds.mini_h, 0); ESetWindowBorderWidth(dd->wins[i], 1); bg = DeskBackgroundGet(DeskGet(i)); if (bg) { EX_Pixmap pmap; pmap = EGetWindowBackgroundPixmap(dd->wins[i]); BackgroundApplyPmap(bg, dd->wins[i], pmap, Mode.backgrounds.mini_w, Mode.backgrounds.mini_h); } else { ic = ImageclassFind("SETTINGS_DESKTOP_AREA", 1); ImageclassApply(ic, dd->wins[i], 0, 0, STATE_NORMAL, ST_SOLID); } } } for (i = dd->desktops - 1; i >= 0; i--) { int num; num = dd->desktops - 1; if (num < 1) num = 1; EMoveWindow(dd->wins[i], (i * (w - Mode.backgrounds.mini_w - 2)) / num, (i * (h - Mode.backgrounds.mini_h - 2)) / num); ERaiseWindow(dd->wins[i]); EMapWindow(dd->wins[i]); } for (i = dd->desktops; i < ENLIGHTENMENT_CONF_NUM_DESKTOPS; i++) { if (!dd->wins[i]) continue; EUnmapWindow(dd->wins[i]); } Esnprintf(s, sizeof(s), "%i", dd->desktops); DialogItemSetText(dd->desk_text, s); } static void CB_DesktopDisplayAreaRedraw(DItem * di, int val __UNUSED__, void *data __UNUSED__) { CB_DesktopDisplayRedraw(DialogItemGetDialog(di), 1, di); } static void _DlgFillDesks(Dialog * d, DItem * table, void *data __UNUSED__) { DItem *di, *slider, *radio; DeskDlgData *dd; dd = DLG_DATA_SET(d, DeskDlgData); if (!dd) return; dd->desktops = Conf.desks.num; dd->prev_desktops = -1; dd->desktop_slide = Conf.desks.slidein; dd->desktop_slide_speed = Conf.desks.slidespeed; dd->desktop_wraparound = Conf.desks.desks_wraparound; if (Conf.desks.dragbar_width < 1) dd->dragbar = 0; else dd->dragbar = 1; dd->dragdir = Conf.desks.dragdir; DialogItemTableSetOptions(table, 2, 0, 0, 0); di = DialogAddItem(table, DITEM_TEXT); DialogItemSetColSpan(di, 2); DialogItemSetText(di, _("Number of virtual desktops:")); di = dd->desk_text = DialogAddItem(table, DITEM_TEXT); DialogItemSetColSpan(di, 2); DialogItemSetText(di, "X"); di = slider = DialogAddItem(table, DITEM_SLIDER); DialogItemSliderSetBounds(di, 1, 32); DialogItemSliderSetUnits(di, 1); DialogItemSliderSetJump(di, 1); DialogItemSetColSpan(di, 2); DialogItemSliderSetValPtr(di, &dd->desktops); di = DialogAddItem(table, DITEM_AREA); DialogItemSetColSpan(di, 2); DialogItemAreaSetSize(di, 2 * Mode.backgrounds.mini_w, 2 * Mode.backgrounds.mini_h); DialogItemAreaSetInitFunc(di, CB_DesktopDisplayAreaRedraw); DialogItemSetCallback(slider, CB_DesktopDisplayRedraw, 0, di); di = DialogAddItem(table, DITEM_SEPARATOR); DialogItemSetColSpan(di, 2); di = DialogAddItem(table, DITEM_CHECKBUTTON); DialogItemSetColSpan(di, 2); DialogItemSetText(di, _("Slide desktops around when changing")); DialogItemCheckButtonSetPtr(di, &dd->desktop_slide); di = DialogAddItem(table, DITEM_TEXT); DialogItemSetColSpan(di, 2); DialogItemSetAlign(di, 1024, 512); DialogItemSetText(di, _("Desktop Slide speed:")); di = DialogAddItem(table, DITEM_SLIDER); DialogItemSetColSpan(di, 2); DialogItemSliderSetBounds(di, 0, 20000); DialogItemSliderSetUnits(di, 500); DialogItemSliderSetJump(di, 1000); DialogItemSliderSetValPtr(di, &dd->desktop_slide_speed); di = DialogAddItem(table, DITEM_SEPARATOR); DialogItemSetColSpan(di, 2); di = DialogAddItem(table, DITEM_CHECKBUTTON); DialogItemSetColSpan(di, 2); DialogItemSetText(di, _("Wrap desktops around")); DialogItemCheckButtonSetPtr(di, &dd->desktop_wraparound); di = DialogAddItem(table, DITEM_SEPARATOR); DialogItemSetColSpan(di, 2); di = DialogAddItem(table, DITEM_CHECKBUTTON); DialogItemSetColSpan(di, 2); DialogItemSetText(di, _("Display desktop dragbar")); DialogItemCheckButtonSetPtr(di, &dd->dragbar); di = DialogAddItem(table, DITEM_TEXT); DialogItemSetColSpan(di, 2); DialogItemSetAlign(di, 0, 512); DialogItemSetText(di, _("Drag bar position:")); radio = di = DialogAddItem(table, DITEM_RADIOBUTTON); DialogItemSetColSpan(di, 2); DialogItemSetText(di, _("Top")); DialogItemRadioButtonSetFirst(di, radio); DialogItemRadioButtonGroupSetVal(di, 2); di = DialogAddItem(table, DITEM_RADIOBUTTON); DialogItemSetColSpan(di, 2); DialogItemSetText(di, _("Bottom")); DialogItemRadioButtonSetFirst(di, radio); DialogItemRadioButtonGroupSetVal(di, 3); di = DialogAddItem(table, DITEM_RADIOBUTTON); DialogItemSetColSpan(di, 2); DialogItemSetText(di, _("Left")); DialogItemRadioButtonSetFirst(di, radio); DialogItemRadioButtonGroupSetVal(di, 0); di = DialogAddItem(table, DITEM_RADIOBUTTON); DialogItemSetColSpan(di, 2); DialogItemSetText(di, _("Right")); DialogItemRadioButtonSetFirst(di, radio); DialogItemRadioButtonGroupSetVal(di, 1); DialogItemRadioButtonGroupSetValPtr(radio, &dd->dragdir); } const DialogDef DlgDesks = { "CONFIGURE_DESKTOPS", N_("Desks"), N_("Multiple Desktop Settings"), SOUND_SETTINGS_DESKTOPS, "pix/desktops.png", N_("Enlightenment Multiple Desktop\n" "Settings Dialog"), _DlgFillDesks, DLG_OAC, CB_ConfigureDesktops, }; typedef struct { int area_x; int area_y; int edge_flip; int edge_resist; DItem *area_text; char area_wraparound; int prev_ax, prev_ay; Win awin; } AreaDlgData; static void CB_ConfigureAreas(Dialog * d, int val, void *data __UNUSED__) { AreaDlgData *dd = DLG_DATA_GET(d, AreaDlgData); if (val >= 2) return; SetNewAreaSize(dd->area_x, dd->area_y); Conf.desks.areas_wraparound = dd->area_wraparound; Conf.desks.edge_flip_mode = dd->edge_flip; if (dd->edge_resist < 1) dd->edge_resist = 1; Conf.desks.edge_flip_resistance = dd->edge_resist; autosave(); } static void CB_AreaDisplayRedraw(Dialog * d, int val, void *data) { AreaDlgData *dd = DLG_DATA_GET(d, AreaDlgData); DItem *di = (DItem *) data; char s[64]; Win win; int w, h, ww, hh; if ((val != 1) && (dd->prev_ax == dd->area_x) && (dd->prev_ay == dd->area_y)) return; dd->prev_ax = dd->area_x; dd->prev_ay = dd->area_y; win = DialogItemAreaGetWindow(di); DialogItemAreaGetSize(di, &w, &h); if (val == 1) { ImageClass *ic; EX_Pixmap pmap; ic = ImageclassFind("SETTINGS_AREA_AREA", 1); ImageclassApply(ic, win, 0, 0, STATE_NORMAL, ST_SOLID); /* Note: awin is destroyed when the dialog is destroyed */ dd->awin = ECreateWindow(win, 0, 0, 18, 14, 0); ic = ImageclassFind("SETTINGS_AREADESK_AREA", 1); pmap = EGetWindowBackgroundPixmap(dd->awin); ImageclassApplySimple(ic, dd->awin, pmap, STATE_NORMAL, 0, 0, 18, 14); } ww = 18 * dd->prev_ax; hh = 14 * dd->prev_ay; EMoveResizeWindow(dd->awin, (w - ww) / 2, (h - hh) / 2, ww, hh); EMapWindow(dd->awin); Esnprintf(s, sizeof(s), "%i x %i", dd->prev_ax, dd->prev_ay); DialogItemSetText(dd->area_text, s); } static void CB_AreaDisplayAreaRedraw(DItem * di, int val __UNUSED__, void *data __UNUSED__) { CB_AreaDisplayRedraw(DialogItemGetDialog(di), 1, di); } static void _DlgFillAreas(Dialog * d, DItem * table, void *data __UNUSED__) { DItem *di, *slider, *slider2, *table2, *radio; AreaDlgData *dd; dd = DLG_DATA_SET(d, AreaDlgData); if (!dd) return; dd->area_wraparound = Conf.desks.areas_wraparound; dd->edge_flip = Conf.desks.edge_flip_mode; dd->edge_resist = Conf.desks.edge_flip_resistance; DesksGetAreaSize(&dd->area_x, &dd->area_y); DialogItemTableSetOptions(table, 1, 0, 0, 0); di = DialogAddItem(table, DITEM_TEXT); DialogItemSetText(di, _("Virtual Desktop size:")); di = dd->area_text = DialogAddItem(table, DITEM_TEXT); DialogItemSetText(di, "X"); table2 = DialogAddItem(table, DITEM_TABLE); DialogItemTableSetOptions(table2, 2, 0, 0, 0); DialogAddItem(table2, DITEM_NONE); di = slider = DialogAddItem(table2, DITEM_SLIDER); DialogItemSliderSetMinLength(di, 10); DialogItemSliderSetBounds(di, 1, 8); DialogItemSliderSetUnits(di, 1); DialogItemSliderSetJump(di, 1); DialogItemSliderSetValPtr(di, &dd->area_x); di = slider2 = DialogAddItem(table2, DITEM_SLIDER); DialogItemSliderSetMinLength(di, 10); DialogItemSliderSetOrientation(di, 0); DialogItemSetFill(di, 0, 1); DialogItemSliderSetBounds(di, 1, 8); DialogItemSliderSetUnits(di, 1); DialogItemSliderSetJump(di, 1); DialogItemSliderSetValPtr(di, &dd->area_y); di = DialogAddItem(table2, DITEM_AREA); DialogItemAreaSetSize(di, 160, 120); DialogItemAreaSetInitFunc(di, CB_AreaDisplayAreaRedraw); DialogItemSetCallback(slider, CB_AreaDisplayRedraw, 0, di); DialogItemSetCallback(slider2, CB_AreaDisplayRedraw, 0, di); DialogAddItem(table, DITEM_SEPARATOR); di = DialogAddItem(table, DITEM_CHECKBUTTON); DialogItemSetText(di, _("Wrap virtual desktops around")); DialogItemCheckButtonSetPtr(di, &dd->area_wraparound); DialogAddItem(table, DITEM_SEPARATOR); di = DialogAddItem(table, DITEM_TEXT); DialogItemSetAlign(di, 0, 512); DialogItemSetText(di, _("Edge Flip Mode:")); radio = di = DialogAddItem(table, DITEM_RADIOBUTTON); DialogItemSetText(di, _("Off")); DialogItemRadioButtonSetFirst(di, radio); DialogItemRadioButtonGroupSetVal(di, EDGE_FLIP_OFF); di = DialogAddItem(table, DITEM_RADIOBUTTON); DialogItemSetText(di, _("On")); DialogItemRadioButtonSetFirst(di, radio); DialogItemRadioButtonGroupSetVal(di, EDGE_FLIP_ON); di = DialogAddItem(table, DITEM_RADIOBUTTON); DialogItemSetText(di, _("Only when moving window")); DialogItemRadioButtonSetFirst(di, radio); DialogItemRadioButtonGroupSetVal(di, EDGE_FLIP_MOVE); DialogItemRadioButtonGroupSetValPtr(radio, &dd->edge_flip); di = DialogAddItem(table, DITEM_TEXT); DialogItemSetText(di, _("Resistance at edge of screen:")); di = DialogAddItem(table, DITEM_SLIDER); DialogItemSliderSetMinLength(di, 10); DialogItemSliderSetBounds(di, 1, 100); DialogItemSliderSetUnits(di, 1); DialogItemSliderSetJump(di, 10); DialogItemSliderSetValPtr(di, &dd->edge_resist); } const DialogDef DlgAreas = { "CONFIGURE_AREA", N_("Areas"), N_("Virtual Desktop Settings"), SOUND_SETTINGS_AREA, "pix/areas.png", N_("Enlightenment Virtual Desktop\n" "Settings Dialog"), _DlgFillAreas, DLG_OAC, CB_ConfigureAreas, }; #endif /* ENABLE_DIALOGS */ /* * IPC functions */ static void DeskOpGoto(unsigned int desk) { Desk *dsk; Desk *pd = DesksGetCurrent(); if (desk >= Conf.desks.num) return; dsk = _DeskGet(desk); DeskGoto(dsk); if (DesksGetCurrent() != pd) SoundPlay(SOUND_DESKTOP_SHUT); } static void DeskOpGotoRel(int drel) { int desk; desk = (int)DesksGetCurrentNum() + drel; if (Conf.desks.desks_wraparound) desk = (desk + Conf.desks.num) % Conf.desks.num; DeskOpGoto((unsigned int)desk); } static void DeskOpDrag(int desk) { DeskDragStart(desk); } static void DesksIpcDesk(const char *params) { const char *p; char cmd[128], prm[128]; int len, value; unsigned int desk; cmd[0] = prm[0] = '\0'; p = params; if (p) { len = 0; sscanf(p, "%100s %100s %n", cmd, prm, &len); p += len; } desk = DesksGetCurrentNum(); if (!p || cmd[0] == '?') { IpcPrintf("Current Desktop: %d/%d\n", desk, Conf.desks.num); } else if (!strncmp(cmd, "set", 3)) { sscanf(prm, "%u", &desk); ChangeNumberOfDesktops(desk); } else if (!strncmp(cmd, "list", 2)) { Desk *dsk; for (desk = 0; desk < Conf.desks.num; desk++) { dsk = _DeskGet(desk); IpcPrintf ("Desk %d: viewable=%d order=%d x,y=%4d,%4d wxh=%4dx%4d area x,y=%d,%d pmap=%#x\n", desk, dsk->viewable, desks.order[desk], EoGetX(dsk), EoGetY(dsk), EoGetW(dsk), EoGetH(dsk), dsk->current_area_x, dsk->current_area_y, dsk->bg.pmap); } } else if (!strncmp(cmd, "goto", 2)) { sscanf(prm, "%u", &desk); DeskOpGoto(desk); } else if (!strncmp(cmd, "next", 2)) { DeskOpGotoRel(1); } else if (!strncmp(cmd, "prev", 2)) { DeskOpGotoRel(-1); } else if (!strncmp(cmd, "back", 2)) { DeskOpGoto(desks.prev_num); } else if (!strncmp(cmd, "this", 2)) { DeskOpGotoRel(0); } else if (!strncmp(cmd, "raise", 2)) { sscanf(prm, "%u", &desk); SoundPlay(SOUND_DESKTOP_RAISE); DeskRaise(desk); } else if (!strncmp(cmd, "lower", 2)) { sscanf(prm, "%u", &desk); SoundPlay(SOUND_DESKTOP_LOWER); DeskLower(desk); } else if (!strcmp(cmd, "drag")) { if (prm[0]) desk = atoi(prm); DeskOpDrag(desk); } else if (!strcmp(cmd, "clear")) { if (!strcmp(prm, "on")) value = 1; else if (!strcmp(prm, "off")) value = 0; else value = !Mode.showing_desktop; EwinsShowDesktop(value); } else if (!strncmp(cmd, "arrange", 3)) { ArrangeEwins(prm); } } static void DesksIpcArea(const char *params) { const char *p; char cmd[128], prm[128]; int len; int ax, ay, dx, dy; cmd[0] = prm[0] = '\0'; p = params; if (p) { len = 0; sscanf(p, "%100s %100s %n", cmd, prm, &len); p += len; } DeskCurrentGetArea(&ax, &ay); if (!p || cmd[0] == '?') { IpcPrintf("Current Area: %d %d\n", ax, ay); } else if (!strncmp(cmd, "set", 3)) { sscanf(params, "%*s %i %i", &ax, &ay); SetNewAreaSize(ax, ay); } else if (!strncmp(cmd, "goto", 2)) { sscanf(params, "%*s %i %i", &ax, &ay); DeskCurrentGotoArea(ax, ay); } else if (!strncmp(cmd, "move", 2)) { dx = dy = 0; sscanf(params, "%*s %i %i", &dx, &dy); DeskCurrentMoveAreaBy(dx, dy); } else if (!strncmp(cmd, "lgoto", 2)) { sscanf(params, "%*s %i", &ax); SetCurrentLinearArea(ax); } else if (!strncmp(cmd, "lmove", 2)) { dx = 0; sscanf(params, "%*s %i", &dx); MoveCurrentLinearAreaBy(dx); } } static const IpcItem DesksIpcArray[] = { { DesksIpcDesk, "desk", NULL, "Desktop functions", " desk ? Desktop info\n" " desk drag Start deskdrag\n" " desk set Set number of desktops\n" " desk goto Goto specified desktop\n" " desk list Show desk info\n" " desk next Goto next desktop\n" " desk prev Goto previous desktop\n" " desk back Goto previous active desktop\n" " desk this Goto this desktop\n" " desk lower Lower desktop\n" " desk raise Raise desktop\n" " desk arrange Arrange windows on desktop\"\n" " desk clear [on/off] \"Show Desktop\"\n"} , { DesksIpcArea, "area", NULL, "Area functions", " area ? Area info\n" " area set Set area size\n" " area goto Goto specified area\n" " area move Move relative to current area\n" " area lgoto Goto specified linear area\n" " area lmove
Move relative to current linear area\n"} , }; #define N_IPC_FUNCS (sizeof(DesksIpcArray)/sizeof(IpcItem)) static void DesksCfgFuncCount(void *item __UNUSED__, const char *value) { ChangeNumberOfDesktops(atoi(value)); } static void DesksCfgFuncDragdir(void *item __UNUSED__, const char *value) { DeskDragdirSet(value); } static void DesksCfgFuncDragdbarOrder(void *item __UNUSED__, const char *value) { DeskDragbarOrderSet(value); } static void AreasCfgFuncSizeX(void *item __UNUSED__, const char *value) { int ax, ay; DesksGetAreaSize(&ax, &ay); SetNewAreaSize(atoi(value), ay); } static void AreasCfgFuncSizeY(void *item __UNUSED__, const char *value) { int ax, ay; DesksGetAreaSize(&ax, &ay); SetNewAreaSize(ax, atoi(value)); } static const CfgItem DesksCfgItems[] = { CFG_FUNC_INT(Conf.desks, num, 2, DesksCfgFuncCount), CFG_FUNC_INT(Conf.desks, dragdir, 2, DesksCfgFuncDragdir), CFG_ITEM_INT(Conf.desks, dragbar_width, 16), CFG_ITEM_INT(Conf.desks, dragbar_length, 0), CFG_FUNC_INT(Conf.desks, dragbar_ordering, 1, DesksCfgFuncDragdbarOrder), CFG_ITEM_BOOL(Conf.desks, desks_wraparound, 0), CFG_ITEM_BOOL(Conf.desks, slidein, 1), CFG_ITEM_INT(Conf.desks, slidespeed, 6000), CFG_FUNC_INT(Conf.desks, areas_nx, 2, AreasCfgFuncSizeX), CFG_FUNC_INT(Conf.desks, areas_ny, 1, AreasCfgFuncSizeY), CFG_ITEM_BOOL(Conf.desks, areas_wraparound, 0), CFG_ITEM_INT(Conf.desks, edge_flip_mode, EDGE_FLIP_ON), CFG_ITEM_INT(Conf.desks, edge_flip_resistance, 25), }; #define N_CFG_ITEMS (sizeof(DesksCfgItems)/sizeof(CfgItem)) /* * Module descriptor */ extern const EModule ModDesktops; const EModule ModDesktops = { "desktops", "desk", DesksSighan, {N_IPC_FUNCS, DesksIpcArray}, {N_CFG_ITEMS, DesksCfgItems} };