22#include "ctwm_atoms.h"
34#define DPRINTF(x) fprintf x
47#define OTP_MAX (OTP_ZERO * 2)
50#define PRI(owl) OwlEffectivePriority(owl)
51#define PRI_CP(from, to) do { \
52 to->pri_base = from->pri_base; \
53 to->pri_aflags = from->pri_aflags; \
123 bool interX = (b1->
x + b1->
width > b2->
x) && (b2->
x + b2->
width > b1->
x);
126 return (interX && interY);
144 &&
OCCUPY(twm_win,
Scr->currentvs->wsw->currentwspc));
155 return ((twm_win->
group == 0)
156 || (twm_win->
group == twm_win->
w));
168 int trans_area, main_area;
171 assert(trans->
frame);
173 main_area =
main->frame_width *
main->frame_height;
175 return (trans_area < ((main_area *
Scr->TransientOnTop) / 100));
194 for(tvs =
Scr->vScreenList; tvs != NULL; tvs = tvs->
next) {
195 fprintf(stderr,
"OtpCheckConsistencyVS: vs:(x,y)=(%d,%d)\n",
210 Window
root, parent, *children;
211 unsigned int nchildren;
216 XQueryTree(
dpy, vroot, &
root, &parent, &children, &nchildren);
221 fprintf(stderr,
"XQueryTree: %d children:\n", nchildren);
223 for(i = 0; i < nchildren; i++) {
224 fprintf(stderr,
"[%d]=%x ", i, (
unsigned int)children[i]);
226 fprintf(stderr,
"\n");
230 for(owl =
Scr->bottomOwl; owl != NULL; owl = owl->
above) {
238 if(owl->
below == NULL) {
239 assert(owl ==
Scr->bottomOwl);
250 const int nextpri =
PRI(owl);
251 if(nextpri < priority) {
252 fprintf(stderr,
"%s(): Priority went backward "
253 "(%d:'%s' -> %d:'%s')\n",
265 fprintf(stderr,
"checking owl: pri %d w=%x stack=%d",
268 fprintf(stderr,
" title=%s occupation=%x ",
272 fprintf(stderr,
" vs:(x,y)=(%d,%d)",
277 fprintf(stderr,
" vs:NULL");
280 fprintf(stderr,
" parent_vs:(x,y)=(%d,%d)",
285 fprintf(stderr,
" parent_vs:NULL");
288 fprintf(stderr,
" %s\n", (owl->
type ==
WinWin ?
"Window" :
"Icon"));
297 if(twm_win->winbox) {
302 DPRINTF((stderr,
"Can't check this window, it is in a WinBox\n"));
317 for(i = 0; i < nchildren && windowOfOwl != children[i];) {
320 fprintf(stderr,
"search for owl in stack -> i=%d\n", i);
321 assert(i > stack &&
"Window not in good place in stack");
322 assert(i < nchildren &&
"Window was not found in stack");
325 snprintf(buf, 128,
"xwininfo -all -id %d", (
int)windowOfOwl);
335 DPRINTF((stderr,
"stack++: children[%d] = %x\n", stack,
336 (
unsigned int)children[stack]));
337 assert(stack < nchildren);
339 while(windowOfOwl != children[stack]);
347 for(twm_win =
Scr->FirstWindow; twm_win != NULL; twm_win = twm_win->
next) {
351 assert((nwins <= 0) && (nwins >= -1));
359 if(owl->
above != NULL) {
362 if(owl->
below != NULL) {
399 while(owl != NULL && owl->
twm_win->winbox != wb) {
405 *owlp = wb->twmwin->otp;
418 fprintf(stderr,
"InsertOwlAbove owl->pri=%d w=0x%x parent_vs:(x,y)=(%d,%d)",
423 if(other_owl != NULL) {
424 fprintf(stderr,
"\n other_owl->pri=%d w=0x%x parent_vs:(x,y)=(%d,%d)",
430 fprintf(stderr,
"\n");
433 assert(owl->
above == NULL);
434 assert(owl->
below == NULL);
437 if(other_owl == NULL) {
438 DPRINTF((stderr,
"Bottom-most window overall\n"));
448 Scr->bottomOwl = owl;
460 else if(winbox != NULL) {
461 vs_owl = GetOwlAtOrBelowInWinbox(&other_owl, winbox);
469 assert(
PRI(owl) >=
PRI(other_owl));
470 if(other_owl->
above != NULL) {
475 DPRINTF((stderr,
"Bottom-most window in VirtualScreen or window box\n"));
485 DPRINTF((stderr,
"General case\n"));
487 assert(
PRI(vs_owl) <=
PRI(other_owl));
491 xwcm = CWStackMode | CWSibling;
493 xwc.stack_mode = Above;
498 owl->
below = other_owl;
501 if(owl->
above != NULL) {
522 if((owl->
type !=
WinWin) || other_owl == NULL) {
527 for(trans_owl = other_owl->
below; trans_owl != NULL; trans_owl = tmp_owl) {
528 tmp_owl = trans_owl->
below;
543 if(priority <=
PRI(
Scr->bottomOwl)) {
547 for(owl1 =
Scr->bottomOwl, owl2 = owl1->
above;
548 (owl2 != NULL) && (
PRI(owl2) < priority);
549 owl1 = owl2, owl2 = owl2->
above) {
553 assert(owl2 == owl1->
above);
554 assert(
PRI(owl1) < priority);
555 assert((owl2 == NULL) || (
PRI(owl2) >= priority));
566 DPRINTF((stderr,
"InsertOwl %s\n",
567 (where == Above) ?
"Above" :
568 (where == Below) ?
"Below" :
570 assert(owl->
above == NULL);
571 assert(owl->
below == NULL);
572 assert((where == Above) || (where == Below));
574 priority =
PRI(owl) - (where == Above ? 0 : 1);
576 if(
Scr->bottomOwl == NULL) {
578 Scr->bottomOwl = owl;
584 while((other_owl != NULL)
588 other_owl = other_owl->
below;
602 DPRINTF((stderr,
"SetOwlPriority(%d)\n", new_pri));
638 other_owl = (other_owl == NULL) ?
Scr->bottomOwl : other_owl->
above;
639 assert(
PRI(other_owl) >=
PRI(owl));
642 while((other_owl != NULL) && (
PRI(other_owl) ==
PRI(owl))) {
667 if(((where == Above) && (priority > owl->
pri_base)) ||
668 ((where == Below) && (priority < owl->pri_base))) {
704 while((other_owl != NULL) && (
PRI(other_owl) ==
PRI(owl))) {
713 other_owl = other_owl->
above;
722 while((other_owl != NULL) && (
PRI(other_owl) ==
PRI(owl))) {
729 other_owl = other_owl->
below;
750 for(other_owl = owl->
above;
751 (other_owl != NULL) && (
PRI(other_owl) <= priority);
752 other_owl = other_owl->
above) {
852 XWindowAttributes winattrs;
855 DPRINTF((stderr,
"OtpCirculateSubwindows %d\n", direction));
857 XGetWindowAttributes(
dpy, w, &winattrs);
858 XSelectInput(
dpy, w, winattrs.your_event_mask | SubstructureNotifyMask);
859 XCirculateSubwindows(
dpy, w, direction);
860 XSelectInput(
dpy, w, winattrs.your_event_mask);
866 circulated = XCheckTypedWindowEvent(
dpy, w, CirculateNotify, &
Event);
888 DPRINTF((stderr,
"OtpHandleCirculateNotify: place=%d\n", place));
890 "OtpHandleCirculateNotify: place equals PlaceOnTop nor PlaceOnBottom");
899 DPRINTF((stderr,
"OtpSetPriority: new_pri=%d\n", new_pri));
903 if(twm_win->winbox != NULL || twm_win->iswinbox) {
909 DPRINTF((stderr,
"invalid OnTopPriority value: %d\n", new_pri));
923 int priority = owl->
pri_base + relpriority;
927 if(twm_win->winbox != NULL || twm_win->iswinbox) {
932 where = relpriority < 0 ? Below : Above;
950 if(twm_win->winbox != NULL || twm_win->iswinbox) {
955 where = priority <
OTP_ZERO ? Below : Above;
969 if(twm_win->winbox != NULL || twm_win->iswinbox) {
995 assert(twm_win->
otp != NULL);
996 assert(other_win->
otp != NULL);
998 if(where == BottomIf) {
1001 if(where != Below) {
1015 if(where == Below) {
1016 other_owl = other_owl->
below;
1035 for(i = 0; i <=
OTP_MAX; i++) {
1075 assert(twm_win->
otp != NULL);
1078 if(twm_win->
icon != NULL) {
1088 assert(owl->
above == NULL);
1089 assert(owl->
below == NULL);
1099 assert(*owlp != NULL);
1119 owl->
type = wintype;
1145 if(parent != NULL) {
1169 bool gotflags =
false;
1170 unsigned aflags = 0, fromstash = 0;
1175 fromstash = (OTP_AFLAG_ABOVE | OTP_AFLAG_BELOW);
1184 aflags &= fromstash;
1190 aflags |= OTP_AFLAG_FULLSCREEN;
1197 aflags |= OTP_AFLAG_ABOVE;
1200 aflags |= OTP_AFLAG_BELOW;
1229 assert(*owlp == NULL);
1235 else if(twm_win->winbox) {
1237 parent = twm_win->winbox->twmwin->
otp;
1244 other_win =
Scr->FirstWindow;
1245 while(other_win != NULL
1248 other_win = other_win->
next;
1250 if(other_win != NULL) {
1251 parent = other_win->
otp;
1256 *owlp =
AddNewOwl(twm_win, wintype, parent);
1258 assert(*owlp != NULL);
1264 if(old_icon != NULL) {
1267 if(new_icon != NULL) {
1268 new_icon->
otp = old_icon->
otp;
1269 old_icon->
otp = NULL;
1282 if(cur_icon != NULL) {
1291 assert(prefs != NULL);
1302 assert(prefs != NULL);
1313 assert(prefs != NULL);
1316 fprintf(stderr,
"invalid OnTopPriority value: %d\n", priority);
1328 assert(prefs != NULL);
1331 fprintf(stderr,
"invalid OnTopPriority value: %d\n", priority);
1344 for(i = 0; i <=
OTP_MAX; i++) {
1359 for(i = 0; i <=
OTP_MAX; i++) {
1368 if(scr->
OTP != NULL) {
1379 Window parent,
int x,
int y)
1384 assert(owl != NULL);
1386 DPRINTF((stderr,
"ReparentWindow: w=%x type=%d\n",
1388 result = XReparentWindow(display,
WindowOfOwl(owl), parent,
x,
y);
1400 Window parent,
int win_x,
int win_y,
1401 int icon_x,
int icon_y)
1404 assert(twm_win->
icon != NULL);
1406 assert(win_owl != NULL);
1407 assert(icon_owl != NULL);
1411 DPRINTF((stderr,
"ReparentWindowAndIcon %x\n", (
unsigned int)twm_win->
frame));
1412 XReparentWindow(display, twm_win->
frame, parent, win_x, win_y);
1413 XReparentWindow(display, twm_win->
icon->
w, parent, icon_x, icon_y);
1419 if(below_win != icon_owl) {
1443 return owl ? owl->
twm_win : NULL;
1455 return top ? top->twm_win : NULL;
1464 return owl ? owl->
twm_win : NULL;
1473 return owl ? owl->
twm_win : NULL;
1487 fprintf(stderr,
"%s():\n", __func__);
1490 fprintf(stderr,
" pri=%2d (%+d) %s 0x%lx:'%1.50s'\n",
1495 fprintf(stderr,
" basepri=%d %s%s%s\n",
1498 (owl->
pri_aflags & OTP_AFLAG_ABOVE ?
" _ABOVE" :
""),
1499 (owl->
pri_aflags & OTP_AFLAG_BELOW ?
" _BELOW" :
""),
1500 (owl->
pri_aflags & OTP_AFLAG_FULLSCREEN ?
" _FULLSCREEN" :
"")
1507 fprintf(stderr,
" transient for 0x%lx:%1.50s\n",
1508 parent->
w, parent->
name);
1512 fprintf(stderr,
" Done.\n");
1524 assert(twm_win != NULL);
1525 assert(twm_win->
otp != NULL);
1532 assert(owl != NULL);
1543 assert(twm_win != NULL);
1544 assert(twm_win->
otp != NULL);
1552 assert(owl != NULL);
1561 assert(twm_win != NULL);
1562 assert(twm_win->
otp != NULL);
1570 assert(owl != NULL);
1602 XChangeProperty(
dpy, owl->
twm_win->
w, XA_CTWM_OTP_AFLAGS, XA_INTEGER,
1603 32, PropModeReplace, (
unsigned char *)&of_prop, 1);
1615 unsigned long nitems, d_after;
1616 unsigned long aflags, *aflags_p;
1624 ret = XGetWindowProperty(
dpy, owl->
twm_win->
w, XA_CTWM_OTP_AFLAGS, 0, 1,
1625 False, XA_INTEGER, &act_type, &d_fmt, &nitems,
1626 &d_after, (
unsigned char **)&aflags_p);
1627 if(ret == Success && act_type == XA_INTEGER && aflags_p != NULL) {
1705 fprintf(stderr,
"%s(): realloc() failed\n", __func__);
1711 while((trans != NULL)) {
1718 tlst[tlused++] = trans;
1721 if(tlused == tlsz) {
1725 fprintf(stderr,
"%s(): realloc() failed\n", __func__);
1738 for(
int i = 0 ; i < tlused ; i++) {
1759 int oldprio =
PRI(twm_win->
otp);
1762 assert(
Scr->Focus == twm_win);
1777 int oldprio =
PRI(twm_win->
otp);
1779 assert(
Scr->Focus != twm_win);
1780 Scr->Focus = twm_win;
1796 assert(twm_win != NULL);
1797 assert(twm_win->
otp != NULL);
1805 assert(twm_win != NULL);
1806 assert(twm_win->
otp != NULL);
1816 assert(owl != NULL);
1862 if(
Scr->Focus == parent) {
1885 assert(twm_win != NULL);
1886 assert(twm_win->
otp != NULL);
int main(int argc, char *argv[])
void HandleCirculateNotify(void)
int EwmhGetInitPriority(TwmWindow *twm_win)
void EwmhSet_NET_WM_STATE(TwmWindow *twm_win, int changes)
void EwmhSet_NET_CLIENT_LIST_STACKING(void)
#define EWMH_PRI_FULLSCREEN
#define EWMH_STATE_FULLSCREEN
int frame_x
X position on screen of frame.
int frame_y
Y position on screen of frame.
Window frame
The X window for the overall frame.
unsigned int frame_width
Width of frame.
unsigned int frame_height
Height of frame.
void FreeList(name_list **list)
void * LookInList(name_list *list_head, const char *name, XClassHint *class)
void OtpSetAflag(TwmWindow *twm_win, unsigned flag)
static void TryToSwitch(OtpWinList *owl, int where)
static bool BoxesIntersect(Box *b1, Box *b2)
static bool shouldStayAbove(OtpWinList *owl, OtpWinList *other_owl)
void OtpChangePriority(TwmWindow *twm_win, WinType wintype, int relpriority)
void OtpScrInitData(ScreenInfo *scr)
static void OwlPrettyPrint(const OtpWinList *start)
Pretty-print a whole OWL stack.
TwmWindow * OtpNextWinDown(TwmWindow *twm_win)
static OtpWinList * new_OtpWinList(TwmWindow *twm_win, WinType wintype, bool switching, int priority)
void OtpAdd(TwmWindow *twm_win, WinType wintype)
static int OwlEffectivePriority(OtpWinList *owl)
static void SetOwlPriority(OtpWinList *owl, int new_pri, int where)
static void InsertOwl(OtpWinList *owl, int where)
bool isTransientOf(TwmWindow *trans, TwmWindow *main)
static void free_OtpPreferences(OtpPreferences *pref)
void OtpSetAflagMask(TwmWindow *twm_win, unsigned mask, unsigned setto)
int OtpEffectivePriority(TwmWindow *twm_win)
static void TinyLowerOwl(OtpWinList *owl)
static Box BoxOfOwl(OtpWinList *owl)
static bool isOnScreen(OtpWinList *owl)
void OtpRestackWindow(TwmWindow *twm_win)
void OtpUnfocusWindow(TwmWindow *twm_win)
Unfocus a window.
static void ApplyPreferences(OtpPreferences *prefs, OtpWinList *owl)
static void OwlStashAflags(OtpWinList *owl)
void OtpTinyLower(TwmWindow *twm_win, WinType wintype)
void OtpTinyRaise(TwmWindow *twm_win, WinType wintype)
static void OwlSetAflagMask(OtpWinList *owl, unsigned mask, unsigned setto)
void OtpHandleCirculateNotify(VirtualScreen *vs, TwmWindow *twm_win, WinType wintype, int place)
void OtpStashAflagsFirstTime(TwmWindow *twm_win)
TwmWindow * OtpNextWinUp(TwmWindow *twm_win)
static void RecomputeOwlPrefs(OtpPreferences *prefs, OtpWinList *owl)
void OtpLower(TwmWindow *twm_win, WinType wintype)
bool isSmallTransientOf(TwmWindow *trans, TwmWindow *main)
static OtpWinList * AddNewOwl(TwmWindow *twm_win, WinType wintype, OtpWinList *parent)
name_list ** OtpScrSwitchingL(ScreenInfo *scr, WinType wintype)
void OtpRecomputePrefs(TwmWindow *twm_win)
void OtpClearAflag(TwmWindow *twm_win, unsigned flag)
static void free_OtpWinList(OtpWinList *owl)
static unsigned OwlGetStashedAflags(OtpWinList *owl, bool *gotit)
static bool isIntersectingWith(OtpWinList *owl1, OtpWinList *owl2)
static OtpWinList * OwlRightBelow(int priority)
int OtpEffectiveDisplayPriority(TwmWindow *twm_win)
static void OwlClearAflag(OtpWinList *owl, unsigned flag)
void OtpFocusWindow(TwmWindow *twm_win)
Focus a window.
static void RaiseSmallTransientsOfAbove(OtpWinList *owl, OtpWinList *other_owl)
void OtpScrSetSwitching(ScreenInfo *scr, WinType wintype, bool switching)
static bool OtpCheckConsistencyVS(VirtualScreen *currentvs, Window vroot)
void OtpRemove(TwmWindow *twm_win, WinType wintype)
bool isGroupLeader(TwmWindow *twm_win)
static void OwlSetAflag(OtpWinList *owl, unsigned flag)
static void InsertOwlAbove(OtpWinList *owl, OtpWinList *other_owl)
static Window WindowOfOwl(OtpWinList *owl)
static void TinyRaiseOwl(OtpWinList *owl)
void OtpForcePlacement(TwmWindow *twm_win, int where, TwmWindow *other_win)
static void RemoveOwl(OtpWinList *owl)
bool OtpCheckConsistency(void)
static OtpWinList * GetOwlAtOrBelowInVS(OtpWinList *owl, VirtualScreen *vs)
For the purpose of putting a window above another, they need to have the same parent,...
static void TryToMoveTransientsOfTo(OtpWinList *owl, int priority, int where)
void OtpFreeIcon(TwmWindow *twm_win)
void OtpToggleSwitching(TwmWindow *twm_win, WinType wintype)
static void RaiseOwl(OtpWinList *owl)
static void OtpFocusWindowBE(TwmWindow *twm_win, int oldprio)
Focus/unfocus backend.
static void RaiseLowerOwl(OtpWinList *owl)
void OtpSetPriority(TwmWindow *twm_win, WinType wintype, int new_pri, int where)
void OtpCirculateSubwindows(VirtualScreen *vs, int direction)
void OtpSwitchPriority(TwmWindow *twm_win, WinType wintype)
bool OtpIsFocusDependent(TwmWindow *twm_win)
void OtpScrSetZero(ScreenInfo *scr, WinType wintype, int priority)
static void LowerOwl(OtpWinList *owl)
void OtpReassignIcon(TwmWindow *twm_win, Icon *old_icon)
bool isGroupLeaderOf(TwmWindow *leader, TwmWindow *twm_win)
void ReparentWindowAndIcon(Display *display, TwmWindow *twm_win, Window parent, int win_x, int win_y, int icon_x, int icon_y)
void OtpRaise(TwmWindow *twm_win, WinType wintype)
TwmWindow * OtpBottomWin(void)
static OtpPreferences * new_OtpPreferences(void)
name_list ** OtpScrPriorityL(ScreenInfo *scr, WinType wintype, int priority)
void OtpRaiseLower(TwmWindow *twm_win, WinType wintype)
TwmWindow * OtpTopWin(void)
int ReparentWindow(Display *display, TwmWindow *twm_win, WinType wintype, Window parent, int x, int y)
static bool isHiddenBy(OtpWinList *owl, OtpWinList *other_owl)
name_list * priorityL[(8 *2)+1]
Info and control for each X Screen we control.
struct OtpPreferences * OTP
Stash of various OTP info about the windows on the screen.
struct OtpPreferences * IconOTP
Stash of OTP info about icons on the screen.
Info and control for every X Window we take over.
struct TwmWindow * next
Next TwmWindow on the Screen.
bool iconified
Has the window ever been iconified?
Window w
The actual X Window handle.
bool istransient
This is a transient window.
char * name
Current window name. Points into TwmWindow::names.
struct Icon * icon
The current icon.
int occupation
Workspaces the window is in (bitmap).
struct VirtualScreen * vs
Where the window is currently mapped (may be NULL).
bool mapped
Is the window mapped ?
XClassHint class
Window class info. From XGetClassHint().
struct VirtualScreen * parent_vs
Where the window is parented. Always set.
OtpWinList * otp
OTP control info for stacking. Created in OtpAdd().
Window transientfor
What window it's transient for.
Window group
Window group, from WM hints.
struct VirtualScreen * next
struct WindowBox WindowBox
TwmWindow * GetTwmWindow(Window w)