Ticket #3600: 3600-Make-it-possible-to-drag-dialogs.patch

File 3600-Make-it-possible-to-drag-dialogs.patch, 6.9 KB (added by mooffie, 6 years ago)
  • lib/widget/dialog.c

    From d615692585c59eab2cbfaf207a063323b08c79d4 Mon Sep 17 00:00:00 2001
    From: Mooffie <mooffie@gmail.com>
    Date: Fri, 26 Feb 2016 16:31:02 +0200
    Subject: [PATCH] Make it possible to drag dialogs.
    
    ---
     lib/widget/dialog.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++-
     lib/widget/dialog.h |   6 ++-
     2 files changed, 111 insertions(+), 2 deletions(-)
    
    diff --git a/lib/widget/dialog.c b/lib/widget/dialog.c
    index a53c046..96108f6 100644
    a b  
    4141#include "lib/tty/key.h" 
    4242#include "lib/strutil.h" 
    4343#include "lib/widget.h" 
     44#include "lib/widget/mouse.h" 
    4445#include "lib/fileloc.h"        /* MC_HISTORY_FILE */ 
    4546#include "lib/event.h"          /* mc_event_raise() */ 
    4647 
    dlg_handle_key (WDialog * h, int d_key) 
    355356    return MSG_NOT_HANDLED; 
    356357} 
    357358 
     359 
    358360/* --------------------------------------------------------------------------------------------- */ 
    359361 
    360362static int 
    361363dlg_mouse_event (WDialog * h, Gpm_Event * event) 
    362364{ 
    363365    Widget *wh = WIDGET (h); 
     366    gboolean mouse_post_processing = ((h->flags & DLG_MOUSE_POST_PROCESSING) != 0); 
    364367 
    365368    GList *p, *first; 
    366369 
    dlg_mouse_event (WDialog * h, Gpm_Event * event) 
    373376        return MOU_NORMAL; 
    374377    } 
    375378 
    376     if (wh->mouse != NULL) 
     379    if (!mouse_post_processing && wh->mouse != NULL) 
    377380    { 
    378381        int mou; 
    379382 
    dlg_mouse_event (WDialog * h, Gpm_Event * event) 
    403406    } 
    404407    while (p != first); 
    405408 
     409    if (mouse_post_processing && wh->mouse != NULL) 
     410    { 
     411        int mou; 
     412 
     413        mou = wh->mouse (event, wh); 
     414        if (mou != MOU_UNHANDLED) 
     415            return mou; 
     416    } 
     417 
    406418    return MOU_UNHANDLED; 
    407419} 
    408420 
    dlg_default_repaint (WDialog * h) 
    604616 
    605617    tty_setcolor (h->color[DLG_COLOR_NORMAL]); 
    606618    dlg_erase (h); 
     619    if (h->is_dragging) 
     620    { 
     621        /* Give feedback to the user when dragging. 
     622         * 
     623         * @FIXME: Have skins define a dedicated color for dragging. We pick 
     624         * 'dtitle' because there doesn't seem to be something better. 
     625         * @TODO: Make WHLine too use this color (when owner is dragged). */ 
     626        tty_setcolor (h->color[DLG_COLOR_TITLE]); 
     627    } 
    607628    tty_draw_box (wh->y + space, wh->x + space, wh->lines - 2 * space, wh->cols - 2 * space, FALSE); 
    608629 
    609630    if (h->title != NULL) 
    dlg_default_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, v 
    769790} 
    770791 
    771792/* --------------------------------------------------------------------------------------------- */ 
     793/** 
     794 * Default dialog mouse callback 
     795 * 
     796 * It lets you drag the dialog by dragging any "empty" space in it (any space 
     797 * that doesn't respond to the mouse, to be exact). 
     798 */ 
     799 
     800static void 
     801dlg_default_mouse_callback (Widget * w, mouse_msg_t msg, mouse_event_t * event) 
     802{ 
     803    WDialog *h = DIALOG (w); 
     804    static int drag_start_x, drag_start_y; 
     805 
     806    if (!h->fullscreen) 
     807    { 
     808        switch (msg) 
     809        { 
     810        case MSG_MOUSE_DOWN: 
     811            h->is_dragging = TRUE; 
     812            drag_start_x = event->x; 
     813            drag_start_y = event->y; 
     814            /* Update the dialog frame (and, in future, HLines) so user sees feedback: */ 
     815            do_refresh ();      /* FIXME: why doesn't `widget_redraw (w)` work? No need to paint the whole screen. */ 
     816            break; 
     817        case MSG_MOUSE_UP: 
     818            h->is_dragging = FALSE; 
     819            /* Update the dialog frame: */ 
     820            do_refresh (); 
     821            break; 
     822        case MSG_MOUSE_DRAG: 
     823            /* The is_idle() check isn't mandatory. It just prevents sluggish 
     824             * drag when the dialogs beneath are CPU-intensive to draw. */ 
     825            if (is_idle ()) 
     826            { 
     827                dlg_move (h, w->x + (event->x - drag_start_x), w->y + (event->y - drag_start_y)); 
     828                do_refresh ();  /* Draw the whole screen. */ 
     829            } 
     830            break; 
     831        default: 
     832            break; 
     833        } 
     834    } 
     835} 
     836 
     837/* --------------------------------------------------------------------------------------------- */ 
    772838 
    773839WDialog * 
    774840dlg_create (gboolean modal, int y1, int x1, int lines, int cols, 
    dlg_create (gboolean modal, int y1, int x1, int lines, int cols, 
    784850                 mouse_handler); 
    785851    widget_want_cursor (w, FALSE); 
    786852 
     853    if (mouse_handler == NULL) 
     854    { 
     855        set_easy_mouse_callback (w, dlg_default_mouse_callback); 
     856        flags |= DLG_MOUSE_POST_PROCESSING; 
     857    } 
     858 
    787859    new_d->state = DLG_CONSTRUCT; 
    788860    new_d->modal = modal; 
    789861    new_d->color = colors; 
    790862    new_d->help_ctx = help_ctx; 
    791863    new_d->flags = flags; 
     864    new_d->is_dragging = FALSE; 
    792865    new_d->data = NULL; 
    793866 
    794867    dlg_set_size (new_d, lines, cols); 
    dlg_destroy (WDialog * h) 
    12891362/* --------------------------------------------------------------------------------------------- */ 
    12901363 
    12911364/** 
     1365 * Moves a dialog to (x, y). 
     1366 * 
     1367 * We need to traverse the child widgets as well because their coordinates 
     1368 * are in aboslute screen coordinates. 
     1369 */ 
     1370void 
     1371dlg_move (WDialog * h, int x, int y) 
     1372{ 
     1373    Widget *wh = WIDGET (h); 
     1374    int dx, dy; 
     1375 
     1376    dx = x - wh->x; 
     1377    dy = y - wh->y; 
     1378 
     1379    wh->x = x; 
     1380    wh->y = y; 
     1381 
     1382    { 
     1383        GList *w; 
     1384 
     1385        for (w = h->widgets; w != NULL; w = g_list_next (w)) 
     1386        { 
     1387            /* FIXME: exclude the WButtonBar (as in the Help dialog). */ 
     1388            WIDGET (w->data)->x += dx; 
     1389            WIDGET (w->data)->y += dy; 
     1390        } 
     1391    } 
     1392} 
     1393 
     1394/* --------------------------------------------------------------------------------------------- */ 
     1395 
     1396/** 
    12921397  * Write history to the ${XDG_CACHE_HOME}/mc/history file 
    12931398  */ 
    12941399void 
  • lib/widget/dialog.h

    diff --git a/lib/widget/dialog.h b/lib/widget/dialog.h
    index 789e5e2..6d886af 100644
    a b typedef enum 
    3737    DLG_CENTER = (1 << 0),      /* Center the dialog */ 
    3838    DLG_TRYUP = (1 << 1),       /* Try to move two lines up the dialog */ 
    3939    DLG_COMPACT = (1 << 2),     /* Suppress spaces around the frame */ 
    40     DLG_WANT_TAB = (1 << 3)     /* Should the tab key be sent to the dialog? */ 
     40    DLG_WANT_TAB = (1 << 3),    /* Should the tab key be sent to the dialog? */ 
     41    DLG_MOUSE_POST_PROCESSING = (1 << 4)        /* Whether mouse events are handed to the dialog *after* child widgets see them (instead of before). */ 
    4142} dlg_flags_t; 
    4243 
    4344/* Dialog state */ 
    struct WDialog 
    9495    dlg_state_t state; 
    9596    gboolean fullscreen;        /* Parents dialogs don't need refresh */ 
    9697    gboolean winch_pending;     /* SIGWINCH signal has been got. Resize dialog after rise */ 
     98    gboolean is_dragging;       /* Whether the dialog is being dragged. */ 
    9799    int mouse_status;           /* For the autorepeat status of the mouse */ 
    98100 
    99101    /* Internal variables */ 
    char *dlg_get_title (const WDialog * h, size_t len); 
    157159 
    158160void dlg_redraw (WDialog * h); 
    159161 
     162void dlg_move (WDialog * h, int x, int y); 
     163 
    160164void dlg_broadcast_msg (WDialog * h, widget_msg_t message); 
    161165 
    162166/* Default callback for dialogs */