@@ -118,7 +118,7 @@ static void cleanup(void);
118
118
static uint32_t getwmdesktop (xcb_drawable_t );
119
119
static void addtoworkspace (struct client * , uint32_t );
120
120
static void grabbuttons (struct client * );
121
- static void delfromworkspace (struct client * , uint32_t );
121
+ static void delfromworkspace (struct client * );
122
122
static void unkillablewindow (struct client * );
123
123
static void fixwindow (struct client * );
124
124
static uint32_t getcolor (const char * );
@@ -188,10 +188,13 @@ focusnext(const Arg *arg)
188
188
}
189
189
190
190
void
191
- delfromworkspace (struct client * client , uint32_t ws )
191
+ delfromworkspace (struct client * client )
192
192
{
193
- delitem (& wslist [ws ], client -> wsitem [ws ]);
194
- client -> wsitem [ws ] = NULL ;
193
+ if (client -> ws < 0 )
194
+ return ;
195
+ delitem (& wslist [client -> ws ], client -> wsitem );
196
+ client -> wsitem = NULL ;
197
+ client -> ws = -1 ;
195
198
}
196
199
197
200
void
@@ -459,7 +462,8 @@ addtoworkspace(struct client *client, uint32_t ws)
459
462
return ;
460
463
461
464
/* Remember our place in the workspace window list. */
462
- client -> wsitem [ws ] = item ;
465
+ client -> wsitem = item ;
466
+ client -> ws = ws ;
463
467
item -> data = client ;
464
468
465
469
/* Set window hint property so we can survive a crash. Like "fixed" */
@@ -482,36 +486,31 @@ changeworkspace_helper(const uint32_t ws)
482
486
xcb_query_pointer_reply_t * pointer ;
483
487
struct client * client ;
484
488
struct item * item ;
485
-
486
-
487
489
if (ws == curws )
488
490
return ;
489
-
490
491
xcb_ewmh_set_current_desktop (ewmh , 0 , ws );
492
+ /* Go through list of current ws.
493
+ * Unmap everything that isn't fixed. */
491
494
for (item = wslist [curws ]; item != NULL ;) {
492
- /* Go through list of current ws.
493
- * Unmap everything that isn't fixed. */
494
495
client = item -> data ;
495
496
item = item -> next ;
496
497
setborders (client ,false);
497
- if (!client -> fixed )
498
+ if (!client -> fixed ){
498
499
xcb_unmap_window (conn , client -> id );
499
- else {
500
+ }else {
501
+ // correct order is delete first add later.
502
+ delfromworkspace (client );
500
503
addtoworkspace (client ,ws );
501
- delfromworkspace (client ,curws );
502
504
}
503
505
}
504
-
505
506
for (item = wslist [ws ]; item != NULL ; item = item -> next ) {
506
507
client = item -> data ;
507
508
if (!client -> fixed && !client -> iconic )
508
509
xcb_map_window (conn , client -> id );
509
510
}
510
-
511
511
curws = ws ;
512
512
pointer = xcb_query_pointer_reply (conn , xcb_query_pointer (conn ,
513
513
screen -> root ), 0 );
514
-
515
514
if (pointer == NULL )
516
515
setfocus (NULL );
517
516
else {
@@ -599,9 +598,9 @@ sendtoworkspace(const Arg *arg)
599
598
{
600
599
if (NULL == focuswin || focuswin -> fixed || arg -> i == curws )
601
600
return ;
602
-
601
+ // correct order is delete first add later.
602
+ delfromworkspace (focuswin );
603
603
addtoworkspace (focuswin , arg -> i );
604
- delfromworkspace (focuswin , curws );
605
604
xcb_unmap_window (conn , focuswin -> id );
606
605
xcb_flush (conn );
607
606
}
@@ -643,14 +642,10 @@ forgetclient(struct client *client)
643
642
644
643
if (NULL == client )
645
644
return ;
646
-
647
645
if (client -> id == top_win )
648
646
top_win = 0 ;
649
-
650
- /* Delete client from the workspace lists it belongs to.
651
- * (can be on several) */
652
- for (ws = 0 ; ws < WORKSPACES ; ws ++ )
653
- if (NULL != client -> wsitem [ws ]) delfromworkspace (client , ws );
647
+ /* Delete client from the workspace list it belongs to. */
648
+ delfromworkspace (client );
654
649
655
650
/* Remove from global window list. */
656
651
freeitem (& winlist , NULL , client -> winitem );
@@ -960,8 +955,8 @@ setupwin(xcb_window_t win)
960
955
client -> winitem = item ;
961
956
962
957
/* Initialize workspace pointers. */
963
- for ( ws = 0 ; ws < WORKSPACES ; ws ++ )
964
- client -> wsitem [ ws ] = NULL ;
958
+ client -> wsitem = NULL ;
959
+ client -> ws = -1 ;
965
960
966
961
/* Get window geometry. */
967
962
getgeom (& client -> id , & client -> x , & client -> y , & client -> width ,
@@ -1503,91 +1498,56 @@ movewindow(xcb_drawable_t win, const int16_t x, const int16_t y)
1503
1498
1504
1499
xcb_flush (conn );
1505
1500
}
1506
-
1507
- /* Change focus to next in window ring. */
1508
1501
void
1509
1502
focusnext_helper (bool arg )
1510
1503
{
1511
1504
struct client * cl = NULL ;
1512
- /* no windows on current workspace*/
1513
- if (NULL == wslist [curws ])
1505
+ struct item * head = wslist [curws ];
1506
+ struct item * tail ,* item = NULL ;
1507
+ // no windows on current workspace
1508
+ if (NULL == head )
1514
1509
return ;
1515
- /* If we currently have no focus focus first in list. */
1516
- if (NULL == focuswin || NULL == focuswin -> wsitem [curws ]) {
1517
- cl = wslist [curws ]-> data ;
1518
- while (cl -> iconic == true && cl -> wsitem [curws ]-> next != NULL )
1519
- cl = cl -> wsitem [curws ]-> next -> data ;
1520
- } else {
1510
+ // if no focus on current workspace, find first valid item on list.
1511
+ if (NULL == focuswin || focuswin -> ws != curws ) {
1512
+ for (item = head ;item != NULL ;item = item -> next ){
1513
+ cl = item -> data ;
1514
+ if (!cl -> iconic )
1515
+ break ;
1516
+ }
1517
+ }else {
1518
+ // find tail of list and make list circular.
1519
+ for (tail = head = item = wslist [curws ]; item != NULL ;
1520
+ tail = item ,item = item -> next );
1521
+ head -> prev = tail ;
1522
+ tail -> next = head ;
1521
1523
if (arg == TWOBWM_FOCUS_NEXT ) {
1522
- if (NULL == focuswin -> wsitem [curws ]-> prev ) {
1523
- /* We were at the head of list.
1524
- * Focusing on last window in list unless
1525
- * we were already there.*/
1526
- cl = wslist [curws ]-> data ;
1527
-
1528
- /* Go to the end of the list */
1529
- while (cl -> wsitem [curws ]-> next != NULL )
1530
- cl = cl -> wsitem [curws ]-> next -> data ;
1531
- /* walk backward until we find
1532
- * a window that isn't iconic */
1533
- while (cl -> iconic == true)
1534
- cl = cl -> wsitem [curws ]-> prev -> data ;
1535
- } else
1536
- if (focuswin != wslist [curws ]-> data ) {
1537
- cl = focuswin -> wsitem [curws ]-> prev -> data ;
1538
- while (cl -> iconic == true
1539
- && cl -> wsitem [curws ]-> prev
1540
- != NULL )
1541
- cl = cl -> wsitem [curws ]-> prev -> data ;
1542
- /* move to the head an didn't find a
1543
- * window to focus so move to the end
1544
- * starting from the focused win */
1545
- if (cl -> iconic == true) {
1546
- cl = focuswin ;
1547
- /* Go to the end of the list */
1548
- while (cl -> wsitem [curws ]-> next
1549
- != NULL )
1550
- cl = cl -> wsitem [curws ]-> next -> data ;
1551
- while (cl -> iconic == true)
1552
- cl = cl -> wsitem [curws ]-> prev -> data ;
1553
- }
1554
- }
1555
- } else {
1556
- /* We were at the tail of list.
1557
- * Focusing on last window in list unless we
1558
- * were already there.*/
1559
- if (NULL == focuswin -> wsitem [curws ]-> next ) {
1560
- /* We were at the end of list.
1561
- * Focusing on first window in list unless we
1562
- * were already there. */
1563
- cl = wslist [curws ]-> data ;
1564
- while (cl -> iconic && cl -> wsitem [curws ]-> next
1565
- != NULL )
1566
- cl = cl -> wsitem [curws ]-> next -> data ;
1567
- } else {
1568
- cl = focuswin -> wsitem [curws ]-> next -> data ;
1569
- while (cl -> iconic == true
1570
- && cl -> wsitem [curws ]-> next
1571
- != NULL )
1572
- cl = cl -> wsitem [curws ]-> next -> data ;
1573
- /* we reached the end of the list without a
1574
- * new win to focus, so reloop from the head */
1575
- if (cl -> iconic == true) {
1576
- cl = wslist [curws ]-> data ;
1577
- while (cl -> iconic
1578
- && cl -> wsitem [curws ]-> next
1579
- != NULL )
1580
- cl = cl -> wsitem [curws ]-> next -> data ;
1581
- }
1582
- }
1524
+ // start from focus next and find first valid item on circular list.
1525
+ head = item = focuswin -> wsitem -> next ;
1526
+ do {
1527
+ cl = item -> data ;
1528
+ if (!cl -> iconic )
1529
+ break ;
1530
+ item = item -> next ;
1531
+ }while (item != head );
1532
+ }else {
1533
+ // start from focus previous and find first valid on circular list.
1534
+ tail = item = focuswin -> wsitem -> prev ;
1535
+ do {
1536
+ cl = item -> data ;
1537
+ if (!cl -> iconic )
1538
+ break ;
1539
+ item = item -> prev ;
1540
+ }while (item != tail );
1583
1541
}
1542
+ // restore list.
1543
+ wslist [curws ]-> prev -> next = NULL ;
1544
+ wslist [curws ]-> prev = NULL ;
1584
1545
}
1585
- /* if NULL focuswin */
1586
- if (NULL != cl && focuswin != cl && cl -> iconic == false) {
1587
- raisewindow (cl -> id );
1588
- centerpointer (cl -> id ,cl );
1589
- setfocus (cl );
1590
- }
1546
+ if (!item || !(cl = item -> data ) || cl -> iconic )
1547
+ return ;
1548
+ raisewindow (cl -> id );
1549
+ centerpointer (cl -> id ,cl );
1550
+ setfocus (cl );
1591
1551
}
1592
1552
/* Mark window win as unfocused. */
1593
1553
void setunfocus (void )
@@ -1609,8 +1569,9 @@ findclient(const xcb_drawable_t *win)
1609
1569
for (item = winlist ; item != NULL ; item = item -> next ) {
1610
1570
client = item -> data ;
1611
1571
1612
- if (* win == client -> id )
1572
+ if (* win == client -> id ){
1613
1573
return client ;
1574
+ }
1614
1575
}
1615
1576
1616
1577
return NULL ;
@@ -1856,7 +1817,7 @@ snapwindow(struct client *client)
1856
1817
void
1857
1818
mousemove (const int16_t rel_x , const int16_t rel_y )
1858
1819
{
1859
- if (focuswin == NULL || focuswin -> wsitem [ curws ] == NULL )
1820
+ if (focuswin == NULL || focuswin -> ws != curws )
1860
1821
return ;
1861
1822
1862
1823
focuswin -> x = rel_x ;
@@ -2282,15 +2243,12 @@ getpointer(const xcb_drawable_t *win, int16_t *x, int16_t *y)
2282
2243
2283
2244
pointer = xcb_query_pointer_reply (conn ,
2284
2245
xcb_query_pointer (conn , * win ), 0 );
2285
-
2246
+ if (NULL == pointer )
2247
+ return false;
2286
2248
* x = pointer -> win_x ;
2287
2249
* y = pointer -> win_y ;
2288
2250
2289
2251
free (pointer );
2290
-
2291
- if (NULL == pointer )
2292
- return false;
2293
-
2294
2252
return true;
2295
2253
}
2296
2254
@@ -2975,7 +2933,6 @@ unmapnotify(xcb_generic_event_t *ev)
2975
2933
{
2976
2934
xcb_unmap_notify_event_t * e = (xcb_unmap_notify_event_t * )ev ;
2977
2935
struct client * client = NULL ;
2978
-
2979
2936
/*
2980
2937
* Find the window in our current workspace list, then forget about it.
2981
2938
* Note that we might not know about the window we got the UnmapNotify
@@ -2990,14 +2947,11 @@ unmapnotify(xcb_generic_event_t *ev)
2990
2947
* If we do this, we need to keep track of our own windows and
2991
2948
* ignore UnmapNotify on them.
2992
2949
*/
2993
-
2994
2950
client = findclient ( & e -> window );
2995
- if (NULL == client || client -> wsitem [ curws ] == NULL )
2951
+ if (NULL == client || client -> ws != curws )
2996
2952
return ;
2997
-
2998
2953
if (focuswin != NULL && client -> id == focuswin -> id )
2999
2954
focuswin = NULL ;
3000
-
3001
2955
if (client -> iconic == false)
3002
2956
forgetclient (client );
3003
2957
0 commit comments