home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 mARCH / PCWK3A99.iso / Linux / DDD331 / DDD-3_1_.000 / DDD-3_1_ / ddd-3.1.1 / ddd / ungrab.C < prev    next >
C/C++ Source or Header  |  1998-10-23  |  7KB  |  269 lines

  1. // $Id: ungrab.C,v 1.17 1998/10/23 15:16:12 zeller Exp $ -*- C++ -*-
  2. // Ungrab frozen mouse pointer
  3.  
  4. // Copyright (C) 1997-1998 Technische Universitaet Braunschweig, Germany.
  5. // Written by Andreas Zeller <zeller@ips.cs.tu-bs.de>.
  6. // 
  7. // This file is part of DDD.
  8. // 
  9. // DDD is free software; you can redistribute it and/or
  10. // modify it under the terms of the GNU General Public
  11. // License as published by the Free Software Foundation; either
  12. // version 2 of the License, or (at your option) any later version.
  13. // 
  14. // DDD is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17. // See the GNU General Public License for more details.
  18. // 
  19. // You should have received a copy of the GNU General Public
  20. // License along with DDD -- see the file COPYING.
  21. // If not, write to the Free Software Foundation, Inc.,
  22. // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23. // 
  24. // DDD is the data display debugger.
  25. // For details, see the DDD World-Wide-Web page, 
  26. // `http://www.cs.tu-bs.de/softech/ddd/',
  27. // or send a mail to the DDD developers <ddd@ips.cs.tu-bs.de>.
  28.  
  29. char ungrab_rcsid[] = 
  30.     "$Id: ungrab.C,v 1.17 1998/10/23 15:16:12 zeller Exp $";
  31.  
  32. #ifdef __GNUG__
  33. #pragma implementation
  34. #endif
  35.  
  36. #include "ungrab.h"
  37.  
  38. #include <X11/Xlib.h>
  39. #include <stdlib.h>
  40. #include <Xm/MessageB.h>
  41.  
  42. #include "AppData.h"
  43. #include "CodeCache.h"
  44. #include "GDBAgent.h"
  45. #include "TimeOut.h"
  46. #include "assert.h"
  47. #include "buttons.h"
  48. #include "ddd.h"
  49. #include "disp-read.h"
  50. #include "file.h"
  51. #include "post.h"
  52. #include "question.h"
  53. #include "status.h"
  54. #include "string-fun.h"
  55. #include "windows.h"
  56. #include "verify.h"
  57. #include "Command.h"
  58. #include "HelpCB.h"
  59. #include "charsets.h"
  60. #include "wm.h"
  61.  
  62.  
  63. //-----------------------------------------------------------------------------
  64. // Checking grab state
  65. //-----------------------------------------------------------------------------
  66.  
  67. // If we interrupt the debugged program while it has grabbed the
  68. // pointer, disaster will occur, as the pointer will remain grabbed
  69. // and users won't be able to to use their display.
  70.  
  71. // We use a second connection for grabbing and ungrabbing, such that
  72. // we do not disturb the grab state of DDD.
  73. static Display *grab_display = 0;
  74.  
  75. // Return true iff pointer is grabbed.
  76. static bool mouse_pointer_grabbed()
  77. {
  78.     if (!app_data.check_grabs)
  79.     {
  80.     if (grab_display != 0 && grab_display != XtDisplay(command_shell))
  81.     {
  82.         XCloseDisplay(grab_display);
  83.         grab_display = 0;
  84.     }
  85.     return false;
  86.     }
  87.  
  88.     if (grab_display == 0)
  89.     grab_display = XOpenDisplay(XDisplayString(XtDisplay(command_shell)));
  90.     if (grab_display == 0)
  91.     grab_display = XtDisplay(command_shell);
  92.  
  93.     // We check whether the pointer is grabbed by attempting to grab
  94.     // it for ourselves.  If it's already grabbed, this may be by our
  95.     // debuggee.
  96.  
  97.     // Warning! Debugging this function may cause your pointer to freeze!
  98.     int grab_result = XGrabPointer(grab_display,
  99.                    DefaultRootWindow(grab_display),
  100.                    True, 0, GrabModeSync, GrabModeSync,
  101.                    None, None, CurrentTime);
  102.  
  103.     if (grab_result == AlreadyGrabbed || grab_result == GrabFrozen)
  104.     return true;
  105.  
  106.     XUngrabPointer(grab_display, CurrentTime);
  107.     XFlush(grab_display);
  108.  
  109.     return false;
  110. }
  111.  
  112. // Return true iff the debuggee is a running X program
  113. static bool running_x_program()
  114. {
  115.     ProgramInfo info;
  116.     if (!info.running)
  117.     return false;        // Not running
  118.  
  119.     // Every X program has an int variable named `_Xdebug'.
  120.     string display_value = gdbValue("_Xdebug");
  121.  
  122.     if (display_value == "")
  123.     return false;        // No X program
  124.  
  125.     // We may check for active connections here (is the display
  126.     // actually open?), but I don't think this is worth it...
  127.  
  128.     return true;        // Okay
  129. }
  130.  
  131.  
  132. //-----------------------------------------------------------------------------
  133. // Automatic continuation
  134. //-----------------------------------------------------------------------------
  135.  
  136. struct GrabCheckLocker {
  137.     static bool lock;
  138.  
  139.     GrabCheckLocker()
  140.     {
  141.     assert(!lock);
  142.     lock = true;
  143.     }
  144.     ~GrabCheckLocker()
  145.     {
  146.     assert(lock);
  147.     lock = false;
  148.     }
  149. };
  150.  
  151. bool GrabCheckLocker::lock = false;
  152.  
  153. static void CheckUngrabCB(XtPointer client_data, XtIntervalId *)
  154. {
  155.     int& count = *((int *)client_data);
  156.  
  157.     // Don't delay further checks
  158.     GrabCheckLocker lock;
  159.  
  160.     static Widget dialog = 0;
  161.     if (dialog == 0)
  162.     {
  163.     dialog = 
  164.         verify(XmCreateWorkingDialog(find_shell(gdb_w), "grab_warning",
  165.                      NULL, 0));
  166.     Delay::register_shell(dialog);
  167.     XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_OK_BUTTON));
  168.     XtAddCallback(dialog, XmNhelpCallback, ImmediateHelpCB, NULL);
  169.     }
  170.  
  171.     if (!mouse_pointer_grabbed() && count > 0)
  172.     {
  173.     // All done - thanks!
  174.     XtUnmanageChild(dialog);
  175.     return;
  176.     }
  177.  
  178.     MString msg = rm("The mouse pointer appears to be frozen.") + cr();
  179.  
  180.     string cmd = app_data.grab_action;
  181.     if (is_quit_cmd(cmd))
  182.     msg += rm("Quitting " + gdb->title());
  183.     else if (cmd == "kill")
  184.     msg += rm("Killing debuggee");
  185.     else if (is_running_cmd(cmd, gdb))
  186.     msg += rm("Continuing execution");
  187.     else
  188.     msg += rm("Taking action");
  189.  
  190.     msg += rm(" automatically");
  191.  
  192.     if (count == 0)
  193.     {
  194.     msg += rm(".");
  195.  
  196.     // Delay has passed -- continue debuggee.
  197.     if (!cmd.contains("\n"))
  198.         cmd += "\n";
  199.  
  200.     while (cmd != "")
  201.     {
  202.         string line = cmd.before('\n');
  203.         gdb_command(line);
  204.         cmd = cmd.after('\n');
  205.     }
  206.     }
  207.     else
  208.     {
  209.     msg += rm(" in ") + tt(itostring(count)) + rm(" seconds.");
  210.     }
  211.     XtVaSetValues(dialog, XmNmessageString, msg.xmstring(), XtPointer(0));
  212.     manage_and_raise(dialog);
  213.  
  214.     if (count > 0)
  215.     {
  216.     // Try again in 1s.
  217.     count--;
  218.     
  219.     XtAppAddTimeOut(XtWidgetToApplicationContext(gdb_w), 1000,
  220.             CheckUngrabCB, XtPointer(&count));
  221.     }
  222. }
  223.  
  224. // Start grab check
  225. static void CheckGrabCB(XtPointer client_data, XtIntervalId *)
  226. {
  227.     XtIntervalId *id = (XtIntervalId *)client_data;
  228.     *id = 0;
  229.  
  230.     // Don't delay further checks
  231.     GrabCheckLocker lock;
  232.  
  233.     Delay delay;
  234.  
  235.     if (!mouse_pointer_grabbed())
  236.     return;
  237.  
  238.     if (!running_x_program())
  239.     return;            // The pointer is not grabbed by our debuggee
  240.  
  241.     static int count;
  242.     count = app_data.grab_action_delay / 1000;
  243.     XtAppAddTimeOut(XtWidgetToApplicationContext(gdb_w), 0,
  244.             CheckUngrabCB, XtPointer(&count));
  245. }
  246.  
  247. // Check for pointer grabs in a few seconds
  248. void check_grabs(bool start)
  249. {
  250.     static XtIntervalId check_grab_timer = 0;
  251.  
  252.     if (GrabCheckLocker::lock)
  253.     return;
  254.  
  255.     if (check_grab_timer != 0)
  256.     {
  257.     XtRemoveTimeOut(check_grab_timer);
  258.     check_grab_timer = 0;
  259.     }
  260.  
  261.     if (!start)
  262.         return;
  263.  
  264.     check_grab_timer = 
  265.     XtAppAddTimeOut(XtWidgetToApplicationContext(gdb_w), 
  266.             app_data.check_grab_delay,
  267.             CheckGrabCB, XtPointer(&check_grab_timer));
  268. }
  269.