]> Dogcows Code - chaz/tint2/commitdiff
fixed decorated window with compiz
authorThierry Lorthiois <lorthiois@bbsoft.fr>
Mon, 5 Jan 2009 21:01:05 +0000 (21:01 +0000)
committerThierry Lorthiois <lorthiois@bbsoft.fr>
Mon, 5 Jan 2009 21:01:05 +0000 (21:01 +0000)
20 files changed:
ChangeLog
README
doc/tint2-0.7.odt
src/Makefile
src/clock/clock.c
src/clock/clock.h
src/config.c
src/config.h
src/panel.c
src/server.c
src/server.h
src/taskbar/task.c
src/taskbar/task.h
src/taskbar/taskbar.c
src/tint.c
src/tint2
src/util/area.c
src/util/area.h
src/util/common.h
tintrc02

index d06bbdf6e05a7975b4b82039c57346b04b3a8e78..a7b0af6a6473655d660cdd1b73a8c0c03bdd12db 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,23 @@
+wmhints.icon_pixmap=icon->xid;
+wmhints.icon_mask=icon->shape;
+XGetWMHints(...);
+XGetWMNormalHints
+
+- fixed bug : detect X11 icons
+- fixed bug : desktop background detection
+- fixed bug : border with compiz ? with xfce composite ? with xcompmanager ?
+- fixed bug : task active/inactive
+- multi_monitor : taskbar follow monitor's order (left to right, top to bottom)
+- WM background with panel padding_x and panel padding_y 
+  => task (x, y) just on taskbar height
+  => draw background just when needed
+
+
+2008-12-30
+- fixed bug : segfault on ConfigureNotify event
 
 2008-11-12
-- fixed segfault with icon
+- fixed bug : segfault with icon
 - panel's left and right padding feel like WM background
   (right click open window managers's menu, ...)
 
diff --git a/README b/README
index 1835446694047695608d6ff6a586793ce230ee6e..b482d514db3bde596be72e929942564ec5d83c1d 100644 (file)
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
 DEPENDENCIES:
-cairo, pango, glib, imlib2
+cairo, pango, glib, imlib2, xrandr, xinerama
 
 ---------------------------------------------------------
 INSTALL:
index 6a99fbbf6da581cb8188c50ac20be052a4913bb4..03af50a1e4b6060cc79f3e70c7c830dad4b3ef52 100644 (file)
Binary files a/doc/tint2-0.7.odt and b/doc/tint2-0.7.odt differ
index 5b8b2b77b76b767ec6d2faf88e98b4190065a8ef..31fe027cd57b81b7a4f808b30300ac83d0351adc 100644 (file)
@@ -22,7 +22,7 @@ endif
 
 $(PROGNAME): $(FILES) $(SYSTRAYOBJ)
        $(CC) $(CFLAGS) -I. -Iutil -Iclock -Itaskbar -Isystray -o $(PROGNAME) $(FILES) $(FLAGS)
-       #strip $(PROGNAME)
+       strip $(PROGNAME)
 
 install:
        mkdir -p $(BINDIR)
index fb5969b6c48e5837e5358e1f578f910ee5ae763e..1b76ec3197cc3aa888126daf070983d6cf963346 100644 (file)
@@ -64,7 +64,7 @@ void init_clock(Clock *clock, int panel_height)
 }
 
 
-int draw_foreground_clock (void *obj, cairo_t *c)
+void draw_foreground_clock (void *obj, cairo_t *c)
 {
    Clock *clock = obj;
    PangoLayout *layout;
@@ -131,6 +131,5 @@ redraw:
    }
    
    g_object_unref (layout);
-   return 0;
 }
 
index 53c4969492c580ff3bbdf86da02fb68a774b80b5..742a2246c505c86fc74c8c667e5a5478b2c1bcee 100644 (file)
@@ -32,7 +32,7 @@ typedef struct Clock {
 // initialize clock : y position, precision, ...
 void init_clock(Clock *clock, int panel_height);
 
-int draw_foreground_clock (void *obj, cairo_t *c);
+void draw_foreground_clock (void *obj, cairo_t *c);
 
 
 #endif
index e4b6c2d5777e812d75a748242fd25595dbf07ef2..9bcc84ca1066cdd5fd4e643a82831261b60d4178 100644 (file)
@@ -575,6 +575,7 @@ void config_finish ()
       free(l0->data);
    }
    g_slist_free(list_back);
+   list_back = NULL;
 }
 
 
index 1fcd1ed26382f4a3d11ee12fc75a65a2e8a24da0..c87925fa2032825988e13d479fdc2087fa31d126 100644 (file)
@@ -9,7 +9,7 @@
 #ifndef CONFIG_H
 #define CONFIG_H
 
-
+// list of background
 GSList *list_back;
 
 
index b9cbcf2dd341dda20a266143aa7fc3886df241b3..6dc2c8c0fb7ac85c3674cc89549fe128fc9b26c4 100644 (file)
@@ -41,7 +41,7 @@ void visual_refresh ()
    // draw child object
    GSList *l = panel.area.list;
    for (; l ; l = l->next)
-      draw (l->data);
+      refresh (l->data);
 
    // main_win doesn't include panel.area.paddingx, so we have WM capabilities on left and right.
    XCopyArea (server.dsp, server.pmap, window.main_win, server.gc, panel.area.paddingx, 0, panel.area.width-(2*panel.area.paddingx), panel.area.height, 0, 0);
@@ -102,6 +102,10 @@ void set_panel_properties (Window win)
    wmhints.flags = InputHint;
    wmhints.input = False;
    XChangeProperty (server.dsp, win, XA_WM_HINTS, XA_WM_HINTS, 32, PropModeReplace, (unsigned char *) &wmhints, sizeof (XWMHints) / 4);
+   
+   // Undecorated
+   long prop[5] = { 2, 0, 0, 0, 0 };
+   XChangeProperty(server.dsp, win, server.atom._MOTIF_WM_HINTS, server.atom._MOTIF_WM_HINTS, 32, PropModeReplace, (unsigned char *) prop, 5);
 }
 
 
@@ -163,7 +167,7 @@ void visible_object()
          panel.area.list = g_slist_append(panel.area.list, taskbar);
       }
    }
-   redraw(&panel.area);
+   set_redraw(&panel.area);
    panel.refresh = 1;
 }
 
@@ -191,7 +195,7 @@ void set_panel_background()
    // copy background panel on desktop window
    XCopyArea (server.dsp, panel.area.pmap, server.root_win, server.gc_root, 0, 0, panel.area.width, panel.area.height, server.posx, server.posy);
 
-   redraw (&panel.area);
+   set_redraw (&panel.area);
 }
 
 
index 2c34415d5660cc6223889f3f888cd45b9ddca56b..82f51b8ef00e6beed3691716616f196078aeda19 100644 (file)
@@ -67,6 +67,7 @@ void server_init_atoms ()
    server.atom._NET_WM_STRUT_PARTIAL = XInternAtom (server.dsp, "_NET_WM_STRUT_PARTIAL", False);
    server.atom.WM_NAME = XInternAtom(server.dsp, "WM_NAME", False);
    server.atom.__SWM_VROOT = XInternAtom(server.dsp, "__SWM_VROOT", False);
+   server.atom._MOTIF_WM_HINTS = XInternAtom(server.dsp, "_MOTIF_WM_HINTS", False);
 }
 
 
index e6e230e49892b3406eaf37ca9d4dfd92cdba4ab8..435aefdc3bb76d4fc684ff6f994ac21f30179bcc 100644 (file)
@@ -52,6 +52,7 @@ typedef struct Global_atom
         Atom _NET_WM_STRUT_PARTIAL;
         Atom WM_NAME;
         Atom __SWM_VROOT;
+        Atom _MOTIF_WM_HINTS;
 } Global_atom;
 
 
index 960b53bfd85cd9fad1b5348eb610febbb38d7eb3..1bac2f6aba95b68e4441dc0e41ece377f9871ff2 100644 (file)
@@ -80,7 +80,7 @@ void add_task (Window win)
    tskbar->area.list = g_slist_append(tskbar->area.list, new_tsk);
 
    if (resize_tasks (tskbar))
-      redraw (&tskbar->area);
+      set_redraw (&tskbar->area);
 }
 
 
@@ -92,7 +92,7 @@ void remove_task (Task *tsk)
    tskbar = (Taskbar*)tsk->area.parent;
    tskbar->area.list = g_slist_remove(tskbar->area.list, tsk);
    resize_tasks (tskbar);
-   redraw (&tskbar->area);
+   set_redraw (&tskbar->area);
    //printf("remove_task %d  %s\n", index(tskbar->desktop, tskbar->monitor), tsk->title);
 
    if (tsk->title) {
@@ -148,18 +148,30 @@ void get_icon (Task *tsk)
    int num;
 
    data = server_get_property (tsk->win, server.atom._NET_WM_ICON, XA_CARDINAL, &num);
-   if (!data) return;
-
-   int w, h;
-   long *tmp_data;
-   tmp_data = get_best_icon (data, get_icon_count (data, num), num, &w, &h, g_task.icon_size1);
-
-   tsk->icon_width = w;
-   tsk->icon_height = h;
-   tsk->icon_data = malloc (w * h * sizeof (long));
-   memcpy (tsk->icon_data, tmp_data, w * h * sizeof (long));
-      
-   XFree (data);
+   if (data) {
+      printf("get_icon plein\n");
+      // ARGB
+      int w, h;
+      long *tmp_data;
+      tmp_data = get_best_icon (data, get_icon_count (data, num), num, &w, &h, g_task.icon_size1);
+
+      tsk->icon_width = w;
+      tsk->icon_height = h;
+      tsk->icon_data = malloc (w * h * sizeof (long));
+      memcpy (tsk->icon_data, tmp_data, w * h * sizeof (long));
+         
+      XFree (data);
+   }
+   else {
+      //XWMHints *hints;
+      //hints = XGetWMHints(server.dsp, tkwin);
+      //if (hints != NULL) {
+      //   XFree(hints);
+      //}
+      printf("get_icon vide\n");
+      // XChangeProperty (display, windowH, XInternAtom (display, "_NET_WM_ICON", False), XA_CARDINAL, 32, PropModeReplace, (unsigned char*) data, dataSize);
+      return;
+   }
 }
 
 
@@ -272,7 +284,16 @@ void draw_task_title (cairo_t *c, Task *tsk, int active)
 }
 
 
-int draw_foreground_task (void *obj, cairo_t *c)
+void draw_background_task (void *obj, cairo_t *c)
+{
+   Task *tsk = obj;
+
+   draw_background (&tsk->area_active, c);
+   draw_background (&tsk->area_inactive, c);
+}
+
+
+void draw_foreground_task (void *obj, cairo_t *c)
 {
    Task *tsk = obj;
    cairo_surface_t *cs;
@@ -292,11 +313,9 @@ int draw_foreground_task (void *obj, cairo_t *c)
    ca = cairo_create (cs);
 
    // redraw task
-   draw_background (&tsk->area_active, ca);
    draw_task_title (ca, tsk, 1);
    
    cairo_destroy (ca);
    cairo_surface_destroy (cs);
-   return 0;
 }
 
index b0c445ac0349f550a9aec5af466d85b33244c450..054eb80f9b9efd551451c59d5d4954d499ec1cf4 100644 (file)
@@ -59,7 +59,7 @@ Global_task g_task;
 void add_task (Window win);
 void remove_task (Task *tsk);
 
-int draw_foreground_task (void *obj, cairo_t *c);
+void draw_foreground_task (void *obj, cairo_t *c);
 
 void get_icon (Task *tsk);
 void get_title(Task *tsk);
index 99e6a17f857248a3e8bf47471619850f62486340..9367ddc28bb978390d72d0bfce87f550188d736a 100644 (file)
@@ -117,7 +117,7 @@ int resize_tasks (Taskbar *taskbar)
       taskbar->task_modulo = modulo_width;
       taskbar->text_width = pixel_width - g_task.text_posx - g_task.area.border.width - g_task.area.paddingx;
    }
-      
+   
    // change pos_x and width for all tasks
    x = taskbar->area.posx + taskbar->area.border.width + taskbar->area.paddingx;
    for (l = taskbar->area.list; l ; l = l->next) {
index 821048bb426fcdd570418e08887f67e920c60cbd..8bf2127c22c714e94d1aebc63565b3e5f8763459 100644 (file)
@@ -63,11 +63,7 @@ void init ()
    panel.clock.area.draw_foreground = draw_foreground_clock;
    g_task.area.draw_foreground = draw_foreground_task;
    window.main_win = 0;
-   
-   // append full transparency background
-   //Area *back = calloc(1, sizeof(Area));
-   list_back = g_slist_append(0, calloc(1, sizeof(Area)));
-   
+      
    server.dsp = XOpenDisplay (NULL);
    if (!server.dsp) {
       fprintf(stderr, "Could not open display.\n");
@@ -355,6 +351,9 @@ int main (int argc, char *argv[])
 load_config:
    if (panel.area.pmap) XFreePixmap (server.dsp, panel.area.pmap);
    panel.area.pmap = 0;                           
+   // append full transparency background
+   list_back = g_slist_append(0, calloc(1, sizeof(Area)));
+
    // read tint2rc config
    i = 0;
    if (c != -1)
@@ -370,8 +369,8 @@ load_config:
    
    window_draw_panel ();
    
-   // BUG: draw(clock) is needed here, but 'on the paper' it's not necessary.
-   draw(&panel.clock.area);
+   // BUG: refresh(clock) is needed here, but 'on the paper' it's not necessary.
+   refresh(&panel.clock.area);
 
    x11_fd = ConnectionNumber (server.dsp);
    XSync (server.dsp, False);
index 2eafd709b40ae3f9b19843e9e603affe5873fa8f..4384d3479fbaf88af98a6a57fb9401aab663cd29 100755 (executable)
Binary files a/src/tint2 and b/src/tint2 differ
index 6585c3e4e1018005c61d2c2e301e4da07640c053..ae84d1dee8b0f6fee13553cbda742b55738b874c 100644 (file)
 #include "area.h"
 
 
-void redraw (Area *a)
+void refresh (Area *a)
+{
+   if (a->redraw) {
+      if (a->draw)
+         a->draw(a);
+      else
+         draw(a);
+   }
+   
+   XCopyArea (server.dsp, a->pmap, server.pmap, server.gc, 0, 0, a->width, a->height, a->posx, a->posy);
+   
+   GSList *l = a->list;
+   // refresh child object (after refreshing parent)
+   for (; l ; l = l->next)
+      refresh(l->data);
+
+   //printf("end refresh area\n");
+}
+
+
+void set_redraw (Area *a)
 {
    a->redraw = 1;
    
    GSList *l;
    for (l = a->list ; l ; l = l->next) 
-      redraw(l->data);
+      set_redraw(l->data);
 }
 
 
-int draw (Area *a)
+void draw (Area *a)
 {
    cairo_surface_t *cs;
    cairo_t *c;
-   int ret = 0;
-
-   if (a->redraw) {
-      //printf("begin draw area\n");
-      if (a->pmap) XFreePixmap (server.dsp, a->pmap);
-      a->pmap = server_create_pixmap (a->width, a->height);
+   
+   //printf("begin draw area\n");
+   if (a->pmap) XFreePixmap (server.dsp, a->pmap);
+   a->pmap = server_create_pixmap (a->width, a->height);
 
-      // add layer of root pixmap
-      XCopyArea (server.dsp, server.pmap, a->pmap, server.gc, a->posx, a->posy, a->width, a->height, 0, 0);
+   // add layer of root pixmap
+   XCopyArea (server.dsp, server.pmap, a->pmap, server.gc, a->posx, a->posy, a->width, a->height, 0, 0);
 
-      cs = cairo_xlib_surface_create (server.dsp, a->pmap, server.visual, a->width, a->height);
-      c = cairo_create (cs);
+   cs = cairo_xlib_surface_create (server.dsp, a->pmap, server.visual, a->width, a->height);
+   c = cairo_create (cs);
 
-      draw_background (a, c);
+   draw_background (a, c);
       
-      if (a->draw_foreground)
-         ret = a->draw_foreground(a, c);
+   if (a->draw_foreground)
+      a->draw_foreground(a, c);
 
-      cairo_destroy (c);
-      cairo_surface_destroy (cs);
-      a->redraw = 0;
-   }
-   
-   XCopyArea (server.dsp, a->pmap, server.pmap, server.gc, 0, 0, a->width, a->height, a->posx, a->posy);
-   
-   GSList *l = a->list;
-   // draw child object
-   for (; l ; l = l->next)
-      draw(l->data);
-
-   //printf("end draw area\n");
-   return ret;
+   cairo_destroy (c);
+   cairo_surface_destroy (cs);
+   a->redraw = 0;
 }
 
 
@@ -84,27 +91,9 @@ void draw_background (Area *a, cairo_t *c)
    if (a->back.alpha > 0.0) {
       //printf("   draw_background %d %d\n", a->width, a->height);
       draw_rect(c, a->border.width, a->border.width, a->width-(2.0 * a->border.width), a->height-(2.0*a->border.width), a->border.rounded - a->border.width/1.571);
-      /*
-      double x0, y0, x1, y1;
-      x0 = 0;
-      y0 = 100;
-      x1 = 100;
-      y1 = 0;
-            
-      cairo_pattern_t *linpat;
-      cairo_matrix_t matrix;
-      linpat = cairo_pattern_create_linear (x0, y0, x1, y1);
-
-      cairo_pattern_add_color_stop_rgba (linpat, 0, a->back.color[0], a->back.color[1], a->back.color[2], a->back.alpha);
-      cairo_pattern_add_color_stop_rgba (linpat, 1, a->back.color[0], a->back.color[1], a->back.color[2], 0);
-      //cairo_matrix_init_scale (&matrix, a->height, a->width);
-      //cairo_pattern_set_matrix (linpat, &matrix);
-      cairo_set_source (c, linpat);
-      */
       cairo_set_source_rgba(c, a->back.color[0], a->back.color[1], a->back.color[2], a->back.alpha);
       
       cairo_fill(c);
-      //cairo_pattern_destroy (linpat);
    }
 
    if (a->border.width > 0 && a->border.alpha > 0.0) {
@@ -163,7 +152,7 @@ void remove_area (Area *a)
    
    parent = (Area*)a->parent;
    parent->list = g_slist_remove(parent->list, a);
-   redraw (parent);
+   set_redraw (parent);
 
 }
 
@@ -174,7 +163,7 @@ void add_area (Area *a)
    
    parent = (Area*)a->parent;
    parent->list = g_slist_remove(parent->list, a);
-   redraw (parent);
+   set_redraw (parent);
 
 }
 
index 5be636f524362a2c679d25c134d83d023b40d48d..0499e1a294439b630e2dd27609904e01756153ba 100644 (file)
@@ -5,60 +5,23 @@
 * Area is at the begining of each graphical object so &object == &area.
 * 
 * Area manage the background and border drawing, size and padding.
-* Area manage also the tree of visible objects
+* Area also manage the tree of visible objects
 *   panel -> taskbars -> tasks
 *         -> systray -> icons
 *         -> clock
 * 
-* un objet comprend les actions:
-* 1) redraw(obj)
-*    force l'indicateur 'redraw' sur l'objet
-*    parcoure la liste des sous objets => redraw(obj)
-* 2) draw(obj)
-*    dessine le background, dessine le contenu dans pmap
-*    parcoure la liste des sous objets => draw(obj)
-*    le pmap de l'objet se base sur le pmap de l'objet parent (cumul des couches)
-* 3) draw_background(obj)
-*    dessine le fond dans pmap
-* 4) draw_foreground(obj) = 0 : fonction virtuelle à redéfinir
-*    dessine le contenu dans pmap
-*    si l'objet n'a pas de contenu, la fonction est nulle
-* 5) resize_width(obj, width) = 0 : fonction virtuelle à redéfinir
+* draw_foreground(obj) and draw(obj) are virtual function.
+* 
+* resize_width(obj, width) = 0 : fonction virtuelle à redéfinir
 *    recalcule la largeur de l'objet (car la hauteur est fixe)
 *    - taille systray calculée à partir de la liste des icones
 *    - taille clock calculée à partir de l'heure
 *    - taille d'une tache calculée à partir de la taskbar (ajout, suppression, taille)
 *    - taille d'une taskbar calculée à partir de la taille du panel et des autres objets
-* 6) voir refresh(obj)
-* 
-* Implémentation :
-* - l'objet est en fait une zone (area). 
-*   l'imbrication des sous objet doit permettre de gérer le layout.
-* - les taches ont 2 objets : l'un pour la tache inactive et l'autre pour la tache active
-*   draw(obj) est appellé sur le premier objet automatiquement 
-*   et draw_foreground(obj) lance l'affichage du 2 ieme objet
-*   ainsi la taskbar gère bien une liste d'objets mais draw(obj) dessine les 2 objets
-* - les fonctions de refresh et de draw sont totalement dissociées
-* 
-* ----------------------------------------------------
-* A évaluer :
-* 1. voir comment définir et gérer le panel_layout avec les objets
-*    => peut on s'affranchir des données spécifiques à chaque objet ?
-*    => comment gérer l'affichage du layout ?
-*    => comment configurer le layout ?
-*    => voir le cumul des couches et l'imbrication entre objet et parent ?
-* 2. voir la fonction de refresh des objets ??
-*    surtout le refresh des taches qui est différent pour la tache active
-* 
-* 3. tester l'implémentation et évaluer les autres abstractions possibles ?
-* 
-* 4. comment gérer le groupage des taches
 * 
 * voir resize_taskbar(), resize_clock() et resize_tasks()
-* voir les taches actives et inactives ?? une seule tache est active !
 * variable widthChanged ou bien emission d'un signal ???
-*
-* 6) config(obj) configure un objet (définie les positions verticales)
+* voir config(obj) configure un objet (définie les positions verticales)
 *
 **************************************************************************/
 
@@ -89,38 +52,40 @@ typedef struct
 
 
 typedef struct {
-   // need redraw Pixmap
-   int redraw;
-   
-   int paddingx, paddingy;   
+   // TODO: isoler 'draw' de 'refresh'
+   // TODO: isoler les données locales des données communes aux freres
+   // absolute coordinate in panel
+   int posx, posy;
    int width, height;
    Pixmap pmap;
+
+   // list of child : Area object
+   GSList *list;
+   
+   // need redraw Pixmap
+   int redraw;   
+   int paddingx, paddingy;   
+   // parent Area
+   void *parent;
    
    Color back;
    Border border;
    
-   // absolute coordinate in panel
-   int posx, posy;
-   // parent Area
-   void *parent;
-
-   // pointer to function
-   // draw_foreground : return 1 if width changed, return O otherwise
-   int (*draw_foreground)(void *obj, cairo_t *c);
+   // each object can overwrite following function
+   void (*draw)(void *obj);
+   void (*draw_foreground)(void *obj, cairo_t *c);
    void (*add_child)(void *obj);
-   int (*remove_child)(void *obj);
-   
-   // list of child : Area object
-   GSList *list;
+   int (*remove_child)(void *obj);   
 } Area;
 
 
-// redraw an area and childs
-void redraw (Area *a);
 
 // draw background and foreground
-// return 1 if width changed, return O otherwise
-int  draw (Area *a);
+void refresh (Area *a);
+
+// set 'redraw' on an area and childs
+void set_redraw (Area *a);
+void draw (Area *a);
 void draw_background (Area *a, cairo_t *c);
 
 void remove_area (Area *a);
index 313a3b71528792a03ffbc1ee01da4f5eed94f55f..09a95a83eb539754fe5e7f20fc41e4d6536c29f2 100644 (file)
 // taskbar table : convert 2 dimension in 1 dimension
 #define index(i, j) ((i * panel.nb_monitor) + j)
 
+/*
+void fxfree(void** ptr){
+  if(*ptr){
+    free(*ptr);
+    *ptr=NULL;
+    }
+  }
+FXint fxmalloc(void** ptr,unsigned long size){
+  *ptr=NULL;
+  if(size!=0){
+    if((*ptr=malloc(size))==NULL) return FALSE;
+    }
+  return TRUE;
+  }
+*/
+
 // mouse actions
 enum { NONE=0, CLOSE, TOGGLE, ICONIFY, SHADE, TOGGLE_ICONIFY };
 
index 4a2c72da7e3fdff7ad2fec8bebdbcd7fbe6a7c1d..538c7f0e3536edd8ed5427f70f6741a88552c552 100644 (file)
--- a/tintrc02
+++ b/tintrc02
@@ -22,7 +22,7 @@ border_color = #cccccc 100
 panel_monitor = 1
 panel_position = bottom right
 panel_size = 0 27
-panel_margin = 0 0
+panel_margin = 0 20
 panel_padding = 4 2
 font_shadow = 0
 panel_background_id = 1
This page took 0.043099 seconds and 4 git commands to generate.