Enlightenment CVS committal

Author  : pfritz
Project : e17
Module  : libs/ewl

Dir     : e17/libs/ewl/src/lib


Modified Files:
        ewl_popup.c ewl_popup.h 


Log Message:
make the popup a bit smarter, i.e. better placing and move into the dektop if 
the mouse reaches the desktop edge

===================================================================
RCS file: /cvs/e/e17/libs/ewl/src/lib/ewl_popup.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -3 -r1.15 -r1.16
--- ewl_popup.c 29 Apr 2007 22:43:38 -0000      1.15
+++ ewl_popup.c 3 Jun 2007 21:20:40 -0000       1.16
@@ -7,6 +7,10 @@
 
 static void ewl_popup_position_check(Ewl_Popup *p);
 static void ewl_popup_size_check(Ewl_Popup *p);
+static int ewl_popup_move_timer(void *data);
+static unsigned int ewl_popup_move_direction_get(Ewl_Popup *p, int *dx, int 
*dy);
+static void ewl_popup_move(Ewl_Popup *p, int dx, int dy);
+static void ewl_popup_move_stop(Ewl_Popup *p);
 
 /**
  * @return Returns pointer to new popup widget on success, NULL on failure.
@@ -67,6 +71,8 @@
         */
        ewl_callback_append(w, EWL_CALLBACK_SHOW, ewl_popup_cb_show, NULL);
        ewl_callback_append(w, EWL_CALLBACK_CONFIGURE, ewl_popup_cb_show, NULL);
+       ewl_callback_append(w, EWL_CALLBACK_MOUSE_MOVE, ewl_popup_cb_mouse_move,
+                                                                       NULL);
        ewl_callback_prepend(w, EWL_CALLBACK_DESTROY, ewl_popup_cb_destroy, 
                                                                        NULL);
 
@@ -294,6 +300,185 @@
  * @param ev_data: UNUSED
  * @param user_data: UNUSED
  * @return Returns no value
+ * @brief The mouse move callback
+ */
+void
+ewl_popup_cb_mouse_move(Ewl_Widget *w, void *ev_data __UNUSED__,
+                               void *user_data __UNUSED__)
+{
+       Ewl_Popup *p;
+       int dx, dy;
+
+       DENTER_FUNCTION(DLEVEL_STABLE);
+       DCHECK_PARAM_PTR("w", w);
+       DCHECK_TYPE("w", w, EWL_POPUP_TYPE);
+
+       p = EWL_POPUP(w);
+
+       /* do we need to move the window? */
+       if (p->moving || !ewl_popup_move_direction_get(p, &dx, &dy))
+               DRETURN(DLEVEL_STABLE);
+
+       /* FIXME the time  schouldn't be a hardcoded value */
+       ecore_timer_add(0.02, ewl_popup_move_timer, p);
+
+       DLEAVE_FUNCTION(DLEVEL_STABLE);
+}
+
+/**
+ * @internal
+ * @param data: The popup widget
+ * @return Returns true to keep the callback, else false
+ * @brief The timer to slide the popup
+ */
+static int
+ewl_popup_move_timer(void *data)
+{
+       Ewl_Popup *p;
+       int dx, dy;
+       int ex, ey, mx, my;
+       
+       DENTER_FUNCTION(DLEVEL_STABLE);
+       DCHECK_PARAM_PTR_RET("data", data, FALSE);
+       DCHECK_TYPE_RET("data", data, EWL_POPUP_TYPE, FALSE);
+
+       p = EWL_POPUP(data);
+
+       if (!ewl_popup_move_direction_get(p, &dx, &dy)) {
+               ewl_popup_move_stop(p);
+               DRETURN_INT(FALSE, DLEVEL_STABLE);
+       }
+
+       /* FIXME the velocity should be configurable and not hardcoded */
+       ewl_popup_move(p, dx * 10, dy * 10);
+       /* since the window now gets moved we have to feed the mouse position
+        * again, because the widgets under the mouse could now be
+        * different */
+       ewl_embed_last_mouse_position_get(&mx, &my);
+       ewl_embed_window_position_get(EWL_EMBED(p), &ex, &ey);
+       ewl_embed_mouse_move_feed(EWL_EMBED(p), mx - ex, my - ey, 0);
+
+       DRETURN_INT(TRUE, DLEVEL_STABLE);       
+}
+
+/**
+ * @internal
+ * @param p: The popup widget
+ * @param dx: The x direction (1, -1 or 0)
+ * @param dy: The y direction (1, -1 or 0)
+ * @return Returns true if the window needs to be moved
+ * @brief determine the move direction
+ */
+static unsigned int
+ewl_popup_move_direction_get(Ewl_Popup *p, int *dx, int *dy)
+{
+       int dw = 0, dh = 0;
+       int x, y, mx, my;
+
+       DENTER_FUNCTION(DLEVEL_STABLE);
+       DCHECK_PARAM_PTR_RET("p", p, FALSE);
+       DCHECK_TYPE_RET("p", p, EWL_POPUP_TYPE, FALSE);
+
+       ewl_embed_desktop_size_get(EWL_EMBED(p), &dw, &dh);
+       ewl_embed_window_position_get(EWL_EMBED(p), &x, &y);
+       ewl_embed_last_mouse_position_get(&mx, &my);
+
+       /* this x and y values are the mouse position relative to the embed */
+       x = mx - x;
+       y = my - y;
+
+       /* check if the mouse is inside of the popup */
+       if (x < 0 || y < 0 || x > CURRENT_W(p) || y > CURRENT_H(p))
+               DRETURN_INT(FALSE, DLEVEL_STABLE);
+
+       /* and now determine the directions of the move */
+       if (mx <= 0)
+               *dx = 1;
+       else if (mx >= dw - 1)
+               *dx = -1;
+       else
+               *dx = 0;
+       
+       if (my <= 0)
+               *dy = 1;
+       else if (my >= dh - 1)
+               *dy = -1;
+       else
+               *dy = 0;
+
+       /* if both are 0 the window doesn't need to be moved */
+       DRETURN_INT((*dx != 0 || *dy != 0), DLEVEL_STABLE);
+}
+
+/**
+ * @internal
+ * @param p: The popup widget
+ * @param dx: The x direction 
+ * @param dy: The y direction
+ * @return Returns nothing
+ * @brief move the popup and its follow if this is also a popup
+ */
+static void 
+ewl_popup_move(Ewl_Popup *p, int dx, int dy)
+{
+       int x, y;
+
+       DENTER_FUNCTION(DLEVEL_STABLE);
+       DCHECK_PARAM_PTR("p", p);
+       DCHECK_TYPE("p", p, EWL_POPUP_TYPE);
+
+       ewl_embed_window_position_get(EWL_EMBED(p), &x, &y);
+       x += dx;
+       y += dy;
+
+       p->moving = TRUE;
+       /* move the follow, too, if it is a popup child */
+       if (p->follow) {
+               Ewl_Embed *e;
+               
+               e = ewl_embed_widget_find(EWL_WIDGET(p->follow));
+               if (EWL_POPUP_IS(e))
+                       ewl_popup_move(EWL_POPUP(e), dx, dy);
+       }
+
+       ewl_window_move(EWL_WINDOW(p), x, y);
+
+       DLEAVE_FUNCTION(DLEVEL_STABLE);
+}
+
+/**
+ * @internal
+ * @param p: The popup widget
+ * @return Returns nothing
+ * @brief set the popup to be not moving and its follow if this is also a popup
+ */
+static void
+ewl_popup_move_stop(Ewl_Popup *p)
+{
+       DENTER_FUNCTION(DLEVEL_STABLE);
+       DCHECK_PARAM_PTR("p", p);
+       DCHECK_TYPE("p", p, EWL_POPUP_TYPE);
+
+       p->moving = FALSE;
+       
+       /* stop moving the follow, too, if it is a popup child */
+       if (p->follow) {
+               Ewl_Embed *e;
+               
+               e = ewl_embed_widget_find(EWL_WIDGET(p->follow));
+               if (EWL_POPUP_IS(e))
+                       ewl_popup_move_stop(EWL_POPUP(e));
+       }
+
+       DLEAVE_FUNCTION(DLEVEL_STABLE);
+}
+
+/**
+ * @internal
+ * @param w: The widget to work with
+ * @param ev_data: UNUSED
+ * @param user_data: UNUSED
+ * @return Returns no value
  * @brief The destroy callback
  */
 void
@@ -419,7 +604,7 @@
        DCHECK_PARAM_PTR("p", p);
        DCHECK_TYPE("p", p, EWL_POPUP_TYPE);
        
-       if (p->type == EWL_POPUP_TYPE_NONE)
+       if (p->type == EWL_POPUP_TYPE_NONE || p->moving)
                DRETURN(DLEVEL_STABLE);
        
        if (p->follow) {
@@ -451,10 +636,11 @@
                x = win_x + CURRENT_X(p->follow);
                y = win_y + CURRENT_Y(p->follow);
                
-               if (x + CURRENT_W(p) > desk_w)
+               if (x + CURRENT_W(p) > desk_w && x > desk_w / 2)
                        x = desk_w - CURRENT_W(p);
                
-               if (y + CURRENT_H(p->follow) + CURRENT_H(p) > desk_h)
+               if (y + CURRENT_H(p->follow) + CURRENT_H(p) > desk_h
+                               && y > desk_h / 2)
                        y -= CURRENT_H(p);
                else
                        y += CURRENT_H(p->follow);
@@ -464,12 +650,13 @@
                x = win_x + CURRENT_X(p->follow);
                y = win_y + CURRENT_Y(p->follow);
 
-               if (x + CURRENT_W(p->follow) + CURRENT_W(p) > desk_w)
+               if (x + CURRENT_W(p->follow) + CURRENT_W(p) > desk_w
+                               && x > desk_w / 2)
                        x -= CURRENT_W(p);
                else
                        x += CURRENT_W(p->follow);
 
-               if (y + CURRENT_H(p) > desk_h)
+               if (y + CURRENT_H(p) > desk_h && y > desk_h / 2)
                        y = desk_h - CURRENT_H(p);
        }
 
===================================================================
RCS file: /cvs/e/e17/libs/ewl/src/lib/ewl_popup.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -3 -r1.11 -r1.12
--- ewl_popup.h 4 Mar 2007 00:52:01 -0000       1.11
+++ ewl_popup.h 3 Jun 2007 21:20:40 -0000       1.12
@@ -49,7 +49,8 @@
                int x;                  /**< The x position */
                int y;                  /**< The y position */
        } mouse, offset;
-       int fit_to_follow;      /**< if the popup fits the size to its follow*/
+       int fit_to_follow:1;    /**< if the popup fits the size to its follow*/
+       int moving:1;           /**< if the popup is currently moving */
 };
 
 Ewl_Widget     *ewl_popup_new(void);
@@ -68,6 +69,7 @@
  * Internal, override at your own risk
  */
 void ewl_popup_cb_show(Ewl_Widget *w, void *ev_data, void *user_data);
+void ewl_popup_cb_mouse_move(Ewl_Widget *w, void *ev_data, void *user_data);
 void ewl_popup_cb_destroy(Ewl_Widget *w, void *ev_data, void *user_data);
 void ewl_popup_cb_child_resize(Ewl_Container *c, Ewl_Widget *w, int size, 
                                        Ewl_Orientation o);



-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
enlightenment-cvs mailing list
enlightenment-cvs@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs

Reply via email to