~cimi/overlay-scrollbar/fix-window-group

« back to all changes in this revision

Viewing changes to os/os-scrollbar.c

  • Committer: Andrea Cimitan
  • Date: 2011-06-08 16:44:43 UTC
  • mfrom: (243.1.7 gtk3)
  • Revision ID: andrea.cimitan@canonical.com-20110608164443-sd6oehapwu7j6lwp
Merged branch gtk3, started from the precious work by Andrea Azzarone

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
#include "os-scrollbar.h"
28
28
#include "os-private.h"
29
29
#include <gdk/gdkx.h>
 
30
#include <X11/extensions/XInput2.h>
30
31
#include "math.h"
31
32
 
32
33
/* Default size of the pager in pixels. */
99
100
static gboolean thumb_motion_notify_event_cb (GtkWidget *widget, GdkEventMotion *event, gpointer user_data);
100
101
static gboolean thumb_scroll_event_cb (GtkWidget *widget, GdkEventScroll *event, gpointer user_data);
101
102
static void thumb_unmap_cb (GtkWidget *widget, gpointer user_data);
 
103
 
 
104
#ifdef USE_GTK3
 
105
static gboolean os_scrollbar_draw (GtkWidget *widget, cairo_t *cr);
 
106
static void os_scrollbar_get_preferred_width (GtkWidget *widget, gint *minimal_width, gint *natural_width);
 
107
static void os_scrollbar_get_preferred_height (GtkWidget *widget, gint *minimal_height, gint *natural_height);
 
108
#else
102
109
static gboolean os_scrollbar_expose_event (GtkWidget *widget, GdkEventExpose *event);
103
 
 
 
110
#endif
104
111
static void os_scrollbar_grab_notify (GtkWidget *widget, gboolean was_grabbed);
105
112
static void os_scrollbar_hide (GtkWidget *widget);
106
113
static void os_scrollbar_map (GtkWidget *widget);
889
896
 
890
897
  gdk_flush ();
891
898
 
 
899
#ifdef USE_GTK3
 
900
  gdk_error_trap_pop_ignored ();
 
901
#else
892
902
  gdk_error_trap_pop ();
 
903
#endif
893
904
}
894
905
 
895
906
/* present a Gdk window */
1117
1128
 
1118
1129
      gdk_flush ();
1119
1130
 
 
1131
#ifdef USE_GTK3
 
1132
      gdk_error_trap_pop_ignored ();
 
1133
#else
1120
1134
      gdk_error_trap_pop ();
 
1135
#endif
1121
1136
    }
1122
1137
}
1123
1138
 
1441
1456
}
1442
1457
 
1443
1458
/* filter function applied to the toplevel window */
 
1459
#ifdef USE_GTK3
 
1460
static GdkFilterReturn
 
1461
toplevel_filter_func (GdkXEvent *gdkxevent,
 
1462
                      GdkEvent  *event,
 
1463
                      gpointer   user_data)
 
1464
{
 
1465
  OsScrollbar *scrollbar;
 
1466
  OsScrollbarPrivate *priv;
 
1467
  XEvent *xev;
 
1468
 
 
1469
  g_return_val_if_fail (OS_SCROLLBAR (user_data), GDK_FILTER_CONTINUE);
 
1470
 
 
1471
  scrollbar = OS_SCROLLBAR (user_data);
 
1472
 
 
1473
  priv = scrollbar->priv;
 
1474
  xev = gdkxevent;
 
1475
 
 
1476
  g_return_val_if_fail (priv->pager != NULL, GDK_FILTER_CONTINUE);
 
1477
  g_return_val_if_fail (priv->thumb != NULL, GDK_FILTER_CONTINUE);
 
1478
 
 
1479
  if (!priv->fullsize)
 
1480
    {
 
1481
      if (xev->type == GenericEvent)
 
1482
        {
 
1483
          XIDeviceEvent *xiev;
 
1484
 
 
1485
          xiev = xev->xcookie.data;
 
1486
 
 
1487
          if (xiev->evtype == XI_ButtonPress)
 
1488
            {
 
1489
              priv->toplevel_button_press = TRUE;
 
1490
              gtk_widget_hide (priv->thumb);
 
1491
            }
 
1492
 
 
1493
          if (priv->toplevel_button_press && xiev->evtype == XI_ButtonRelease)
 
1494
            {
 
1495
              priv->toplevel_button_press = FALSE;
 
1496
 
 
1497
              /* proximity area */
 
1498
              if (priv->orientation == GTK_ORIENTATION_VERTICAL)
 
1499
                {
 
1500
                  if ((priv->thumb_all.x - xiev->event_x <= PROXIMITY_WIDTH &&
 
1501
                       priv->thumb_all.x - xiev->event_x >= 0) &&
 
1502
                      (xiev->event_y >= priv->thumb_all.y + priv->overlay.y &&
 
1503
                       xiev->event_y <= priv->thumb_all.y + priv->overlay.y + priv->overlay.height))
 
1504
                    {
 
1505
                      priv->can_hide = FALSE;
 
1506
 
 
1507
                      if (priv->lock_position)
 
1508
                        return GDK_FILTER_CONTINUE;
 
1509
 
 
1510
                      if (priv->overlay.height > priv->slider.height)
 
1511
                        {
 
1512
                          gint x, y, x_pos, y_pos;
 
1513
 
 
1514
                          gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);
 
1515
 
 
1516
                          x = priv->thumb_all.x;
 
1517
                          y = CLAMP (xiev->event_y - priv->slider.height / 2,
 
1518
                                     priv->thumb_all.y + priv->overlay.y,
 
1519
                                     priv->thumb_all.y + priv->overlay.y + priv->overlay.height - priv->slider.height);
 
1520
 
 
1521
                          move_thumb (scrollbar, x_pos + x, y_pos + y);
 
1522
                        }
 
1523
                      else
 
1524
                        {
 
1525
                          move_thumb (scrollbar, priv->win_x, priv->win_y + priv->slider.y);
 
1526
                        }
 
1527
 
 
1528
                      gtk_widget_show (GTK_WIDGET (priv->thumb));
 
1529
                    }
 
1530
                }
 
1531
              else
 
1532
                {
 
1533
                  if ((priv->thumb_all.y - xiev->event_y <= PROXIMITY_WIDTH &&
 
1534
                       priv->thumb_all.y - xiev->event_y >= 0) &&
 
1535
                      (xiev->event_x >= priv->thumb_all.x + priv->overlay.x &&
 
1536
                       xiev->event_x <= priv->thumb_all.x + priv->overlay.x + priv->overlay.width))
 
1537
                    {
 
1538
                      priv->can_hide = FALSE;
 
1539
 
 
1540
                      if (priv->lock_position)
 
1541
                        return GDK_FILTER_CONTINUE;
 
1542
 
 
1543
                      if (priv->overlay.width > priv->slider.width)
 
1544
                        {
 
1545
                          gint x, y, x_pos, y_pos;
 
1546
 
 
1547
                          gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);
 
1548
 
 
1549
                          x = CLAMP (xiev->event_x - priv->slider.width / 2,
 
1550
                                     priv->thumb_all.x + priv->overlay.x,
 
1551
                                     priv->thumb_all.x + priv->overlay.x + priv->overlay.width - priv->slider.width);
 
1552
                          y = priv->thumb_all.y;
 
1553
 
 
1554
                          move_thumb (scrollbar, x_pos + x, y_pos + y);
 
1555
                        }
 
1556
                      else
 
1557
                        {
 
1558
                          move_thumb (scrollbar, priv->win_x, priv->win_y + priv->slider.y);
 
1559
                        }
 
1560
 
 
1561
                      gtk_widget_show (GTK_WIDGET (priv->thumb));
 
1562
                    }
 
1563
                }
 
1564
            }
 
1565
 
 
1566
          /* after a scroll-event, without motion,
 
1567
           * pager becomes inactive because the timeout in
 
1568
           * leave-notify-event starts,
 
1569
           * this call checks the pointer after the scroll-event,
 
1570
           * since it enters the window,
 
1571
           * then sets the state accordingly. */
 
1572
          if (!priv->active_window && xiev->evtype == XI_Enter)
 
1573
            {
 
1574
              XIEnterEvent *xiee = xev->xcookie.data;
 
1575
 
 
1576
              pager_set_state_from_pointer (scrollbar, xiee->event_x, xiee->event_y);
 
1577
            }
 
1578
 
 
1579
          if (xiev->evtype == XI_Leave)
 
1580
            {
 
1581
              /* never deactivate the pager in an active window. */
 
1582
              if (!priv->active_window)
 
1583
                {
 
1584
                  priv->can_deactivate_pager = TRUE;
 
1585
 
 
1586
                  if (priv->source_deactivate_pager_id != 0)
 
1587
                    g_source_remove (priv->source_deactivate_pager_id);
 
1588
 
 
1589
                  priv->source_deactivate_pager_id = g_timeout_add (TIMEOUT_TOPLEVEL_HIDE,
 
1590
                                                                    deactivate_pager_cb,
 
1591
                                                                    scrollbar);
 
1592
                }
 
1593
 
 
1594
              priv->toplevel_button_press = FALSE;
 
1595
              priv->can_hide = TRUE;
 
1596
 
 
1597
              if (priv->source_hide_thumb_id != 0)
 
1598
                g_source_remove (priv->source_hide_thumb_id);
 
1599
 
 
1600
              priv->source_hide_thumb_id = g_timeout_add (TIMEOUT_TOPLEVEL_HIDE,
 
1601
                                                          hide_thumb_cb,
 
1602
                                                          scrollbar);
 
1603
 
 
1604
              if (priv->source_unlock_thumb_id != 0)
 
1605
                g_source_remove (priv->source_unlock_thumb_id);
 
1606
 
 
1607
              priv->source_unlock_thumb_id = g_timeout_add (TIMEOUT_TOPLEVEL_HIDE,
 
1608
                                                            unlock_thumb_cb,
 
1609
                                                            scrollbar);
 
1610
            }
 
1611
 
 
1612
          /* get the motion_notify_event trough XEvent */
 
1613
          if (!priv->toplevel_button_press && xiev->evtype == XI_Motion)
 
1614
            {
 
1615
              /* react to motion_notify_event
 
1616
               * and set the state accordingly. */
 
1617
              if (!priv->active_window)
 
1618
                pager_set_state_from_pointer (scrollbar, xiev->event_x, xiev->event_y);
 
1619
 
 
1620
              /* proximity area */
 
1621
              if (priv->orientation == GTK_ORIENTATION_VERTICAL)
 
1622
                {
 
1623
                  if ((priv->thumb_all.x - xiev->event_x <= PROXIMITY_WIDTH &&
 
1624
                       priv->thumb_all.x - xiev->event_x >= 0) &&
 
1625
                      (xiev->event_y >= priv->thumb_all.y + priv->overlay.y &&
 
1626
                       xiev->event_y <= priv->thumb_all.y + priv->overlay.y + priv->overlay.height))
 
1627
                    {
 
1628
                      priv->can_hide = FALSE;
 
1629
 
 
1630
                      if (priv->lock_position)
 
1631
                        return GDK_FILTER_CONTINUE;
 
1632
 
 
1633
                      if (priv->overlay.height > priv->slider.height)
 
1634
                        {
 
1635
                          gint x, y, x_pos, y_pos;
 
1636
 
 
1637
                          gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);
 
1638
 
 
1639
                          x = priv->thumb_all.x;
 
1640
                          y = CLAMP (xiev->event_y - priv->slider.height / 2,
 
1641
                                     priv->thumb_all.y + priv->overlay.y,
 
1642
                                     priv->thumb_all.y + priv->overlay.y + priv->overlay.height - priv->slider.height);
 
1643
 
 
1644
                          move_thumb (scrollbar, x_pos + x, y_pos + y);
 
1645
                        }
 
1646
                      else
 
1647
                        {
 
1648
                          move_thumb (scrollbar, priv->win_x, priv->win_y + priv->slider.y);
 
1649
                        }
 
1650
 
 
1651
                      os_pager_set_detached (OS_PAGER (priv->pager), FALSE);
 
1652
                      os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
 
1653
                      gtk_widget_show (GTK_WIDGET (priv->thumb));
 
1654
                    }
 
1655
                  else
 
1656
                    {
 
1657
                      priv->can_hide = TRUE;
 
1658
                      priv->lock_position = FALSE;
 
1659
                      hide_thumb (scrollbar);
 
1660
                    }
 
1661
                }
 
1662
              else
 
1663
                {
 
1664
                  if ((priv->thumb_all.y - xiev->event_y <= PROXIMITY_WIDTH &&
 
1665
                       priv->thumb_all.y - xiev->event_y >= 0) &&
 
1666
                      (xiev->event_x >= priv->thumb_all.x + priv->overlay.x &&
 
1667
                       xiev->event_x <= priv->thumb_all.x + priv->overlay.x + priv->overlay.width))
 
1668
                    {
 
1669
                      priv->can_hide = FALSE;
 
1670
 
 
1671
                      if (priv->lock_position)
 
1672
                        return GDK_FILTER_CONTINUE;
 
1673
 
 
1674
                      if (priv->overlay.width > priv->slider.width)
 
1675
                        {
 
1676
                          gint x, y, x_pos, y_pos;
 
1677
 
 
1678
                          gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (scrollbar)), &x_pos, &y_pos);
 
1679
 
 
1680
                          x = CLAMP (xiev->event_x - priv->slider.width / 2,
 
1681
                                     priv->thumb_all.x + priv->overlay.x,
 
1682
                                     priv->thumb_all.x + priv->overlay.x + priv->overlay.width - priv->slider.width);
 
1683
                          y = priv->thumb_all.y;
 
1684
 
 
1685
                          move_thumb (scrollbar, x_pos + x, y_pos + y);
 
1686
                        }
 
1687
                      else
 
1688
                        {
 
1689
                          move_thumb (scrollbar, priv->win_x + priv->slider.x, priv->win_y);
 
1690
                        }
 
1691
 
 
1692
                      os_pager_set_detached (OS_PAGER (priv->pager), FALSE);
 
1693
                      os_thumb_set_detached (OS_THUMB (priv->thumb), FALSE);
 
1694
                      gtk_widget_show (GTK_WIDGET (priv->thumb));
 
1695
                    }
 
1696
                  else
 
1697
                    {
 
1698
                      priv->can_hide = TRUE;
 
1699
                      priv->lock_position = FALSE;
 
1700
                      hide_thumb (scrollbar);
 
1701
                    }
 
1702
                }
 
1703
            }
 
1704
        }
 
1705
    }
 
1706
 
 
1707
  return GDK_FILTER_CONTINUE;
 
1708
}
 
1709
#else
1444
1710
static GdkFilterReturn
1445
1711
toplevel_filter_func (GdkXEvent *gdkxevent,
1446
1712
                      GdkEvent  *event,
1679
1945
 
1680
1946
  return GDK_FILTER_CONTINUE;
1681
1947
}
 
1948
#endif
1682
1949
 
1683
1950
G_DEFINE_TYPE (OsScrollbar, os_scrollbar, GTK_TYPE_SCROLLBAR);
1684
1951
 
1691
1958
  gobject_class = G_OBJECT_CLASS (class);
1692
1959
  widget_class = GTK_WIDGET_CLASS (class);
1693
1960
 
1694
 
  widget_class->expose_event  = os_scrollbar_expose_event;
1695
 
  widget_class->grab_notify   = os_scrollbar_grab_notify;
1696
 
  widget_class->hide          = os_scrollbar_hide;
1697
 
  widget_class->map           = os_scrollbar_map;
1698
 
  widget_class->realize       = os_scrollbar_realize;
1699
 
  widget_class->show          = os_scrollbar_show;
1700
 
  widget_class->size_allocate = os_scrollbar_size_allocate;
1701
 
  widget_class->size_request  = os_scrollbar_size_request;
1702
 
  widget_class->unmap         = os_scrollbar_unmap;
1703
 
  widget_class->unrealize     = os_scrollbar_unrealize;
 
1961
#ifdef USE_GTK3
 
1962
  widget_class->draw                 = os_scrollbar_draw;
 
1963
  widget_class->get_preferred_width  = os_scrollbar_get_preferred_width;
 
1964
  widget_class->get_preferred_height = os_scrollbar_get_preferred_height;
 
1965
#else
 
1966
  widget_class->expose_event         = os_scrollbar_expose_event;
 
1967
#endif
 
1968
  widget_class->grab_notify          = os_scrollbar_grab_notify;
 
1969
  widget_class->hide                 = os_scrollbar_hide;
 
1970
  widget_class->map                  = os_scrollbar_map;
 
1971
  widget_class->realize              = os_scrollbar_realize;
 
1972
  widget_class->show                 = os_scrollbar_show;
 
1973
  widget_class->size_allocate        = os_scrollbar_size_allocate;
 
1974
#ifndef USE_GTK3
 
1975
  widget_class->size_request         = os_scrollbar_size_request;
 
1976
#endif
 
1977
  widget_class->unmap                = os_scrollbar_unmap;
 
1978
  widget_class->unrealize            = os_scrollbar_unrealize;
1704
1979
 
1705
1980
  gobject_class->dispose  = os_scrollbar_dispose;
1706
1981
  gobject_class->finalize = os_scrollbar_finalize;
1828
2103
  G_OBJECT_CLASS (os_scrollbar_parent_class)->finalize (object);
1829
2104
}
1830
2105
 
 
2106
#ifdef USE_GTK3
 
2107
static gboolean
 
2108
os_scrollbar_draw (GtkWidget      *widget,
 
2109
                   cairo_t        *cr)
 
2110
{
 
2111
  return TRUE;
 
2112
}
 
2113
#else
1831
2114
static gboolean
1832
2115
os_scrollbar_expose_event (GtkWidget      *widget,
1833
2116
                           GdkEventExpose *event)
1834
2117
{
1835
2118
  return TRUE;
1836
2119
}
 
2120
#endif
 
2121
 
 
2122
#if USE_GTK3
 
2123
static void
 
2124
os_scrollbar_get_preferred_width (GtkWidget *widget,
 
2125
                                  gint      *minimal_width,
 
2126
                                  gint      *natural_width)
 
2127
{
 
2128
  GtkRequisition requisition;
 
2129
 
 
2130
  os_scrollbar_size_request (widget, &requisition);
 
2131
 
 
2132
  *minimal_width = *natural_width = requisition.width;
 
2133
}
 
2134
 
 
2135
static void
 
2136
os_scrollbar_get_preferred_height (GtkWidget *widget,
 
2137
                                   gint      *minimal_height,
 
2138
                                   gint      *natural_height)
 
2139
{
 
2140
  GtkRequisition requisition;
 
2141
 
 
2142
  os_scrollbar_size_request (widget, &requisition);
 
2143
 
 
2144
  *minimal_height = *natural_height = requisition.height;
 
2145
}
 
2146
#endif
1837
2147
 
1838
2148
static void
1839
2149
os_scrollbar_grab_notify (GtkWidget *widget,
1981
2291
    {
1982
2292
      priv->slider.width = DEFAULT_THUMB_HEIGHT;
1983
2293
      priv->slider.height = DEFAULT_THUMB_WIDTH;
1984
 
      priv->overlay_all.y = allocation->y - DEFAULT_PAGER_WIDTH ;
 
2294
      priv->overlay_all.y = allocation->y - DEFAULT_PAGER_WIDTH;
1985
2295
      priv->thumb_all.y = allocation->y + THUMB_ALLOCATION_SHIFT;
1986
2296
 
1987
2297
      rect.x = priv->overlay_all.x;
2023
2333
  else
2024
2334
    requisition->height = 0;
2025
2335
 
 
2336
#ifndef USE_GTK3
2026
2337
  widget->requisition = *requisition;
 
2338
#endif
2027
2339
}
2028
2340
 
2029
2341
static void