This is the mail archive of the cygwin-apps mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Incidental setup.exe patches #1: Add busy cursor.



  While working on setup I've ended up fixing a few uncontroversial bits and
pieces along the way, so I'd like to separate those patches out and send them
first.  Here's one that adds support in the Window class for enabling the
busy/hourglass cursor, and invokes it in a couple of places where we have long
operations.  It's not comprehensive but it's a start and makes it trivial for
us to fix for any other long-running operation we want the user not to worry
has crashed.

  There's also one unrelated change in there which I considered too close to
an obvious fix to think worth separating out.  In all windows applications,
there is one HINSTANCE handle to the singleton application instance, and as is
traditional setup.exe keeps a global static copy of that handle for use when
needed by the Windows GUI APIs.  It's a singleton, it's pointed to by a static
class member, and the setter method is a static member method (hence can be
called without a this-pointer); I'm sure it's just a trivial oversight that
the getter method is in fact non-static and thus requires a this-pointer only
in order to ignore the object instance it points to and return a global.
(This has made no difference yet because all existing calls to GetInstance
just happen to be inside non-static member functions of the various dialog
page classes derived from Window, and so have suitable this-pointers available
to invoke it with, but that's by good fortune rather than necessity, and
anyway, let's save ourselves some register pressure by not passing an unused
parameter....)

	* window.cc (Window::Window): Initialise BusyCount and BusyCursor.
	(Window::SetBusy): Set hourglass cursor, counting nested activations.
	(Window::ClearBusy): Cancel one call to SetBusy and restore original
	cursor if no longer busy.
	* window.h (Window::BusyCount): New data member.
	(Window::OldCursor): Likewise.
	(Window::BusyCursor): Likewise.
	(Window::SetBusy): Prototype.
	(Window::ClearBusy): Likewise.
	* choose.cc (ChooserPage::createListview): Invoke busy cursor
	around long-running operation.
	(ChooserPage::OnInit): Likewise.
	(ChooserPage::changeTrust): Likewise.
	* PickCategoryLine.cc (PickCategoryLine::set_action): Likewise.

  OK?

    cheers,
      DaveK




Index: window.cc
===================================================================
RCS file: /cvs/cygwin-apps/setup/window.cc,v
retrieving revision 2.15
diff -p -u -r2.15 window.cc
--- window.cc	15 Apr 2006 21:21:25 -0000	2.15
+++ window.cc	12 Apr 2010 20:32:16 -0000
@@ -31,6 +31,9 @@ Window::Window ()
   WindowHandle = NULL;
   Parent = NULL;
   TooltipHandle = NULL;
+  BusyCount = 0;
+  BusyCursor = NULL;
+
 }
 
 Window::~Window ()
@@ -487,3 +490,29 @@ Window::TooltipNotificationHandler (LPAR
   return FALSE;
 }
 
+void
+Window::SetBusy (void)
+{
+  // The docs suggest that you can call SetCursor, and it won't do
+  // anything if you've chosen the same cursor as is already set.
+  // However it looked to me as if it was resetting the animation
+  // frame every time when I tried it, hence this routine to make
+  // sure we only call it once on the way into and once on the way
+  // out of busy mode.
+  if (BusyCount++ == 0)
+    {
+      if (BusyCursor == NULL)
+	BusyCursor = LoadCursor (NULL, IDC_WAIT);
+      OldCursor = SetCursor (BusyCursor);
+    }
+}
+
+void
+Window::ClearBusy (void)
+{
+  if (BusyCount && (--BusyCount == 0))
+    {
+      SetCursor (OldCursor);
+    }
+}
+
Index: window.h
===================================================================
RCS file: /cvs/cygwin-apps/setup/window.h,v
retrieving revision 2.12
diff -p -u -r2.12 window.h
--- window.h	15 Apr 2006 21:21:25 -0000	2.12
+++ window.h	12 Apr 2010 20:32:16 -0000
@@ -56,7 +56,18 @@ private:
   
   // maps a control ID to a string resource ID
   std::map<int, int> TooltipStrings;
-  
+
+  // Recursive count of number of times we've called SetBusy,
+  // so that we only reset the cursor when we've cleared it
+  // the same number of times.
+  int BusyCount;
+
+  // Saved old cursor handle, only while BusyCount is non-zero.
+  HCURSOR OldCursor;
+
+  // Handle to busy cursor (loaded first time needed, NULL until then).
+  HCURSOR BusyCursor;
+
 protected:
   void SetHWND (HWND h)
   {
@@ -92,7 +103,7 @@ public:
     // Ideally this could be hidden from the user completely.
     return WindowHandle;
   };
-  HINSTANCE GetInstance () const
+  static HINSTANCE GetInstance ()
   {
     return AppInstance;
   };
@@ -147,6 +158,11 @@ public:
   void AddTooltip (int id, const char *text);
   void AddTooltip (int id, int string_resource);
   BOOL TooltipNotificationHandler (LPARAM lParam);
+  // Call this to set an hourglass cursor.
+  void SetBusy (void);
+  // Call this to reset to normal cursor.  It must be called
+  // once for each call to SetBusy; they nest recursively.
+  void ClearBusy (void);
 };
 
 #endif /* SETUP_WINDOW_H */
Index: choose.cc
===================================================================
RCS file: /cvs/cygwin-apps/setup/choose.cc,v
retrieving revision 2.154
diff -p -u -r2.154 choose.cc
--- choose.cc	15 Feb 2010 00:45:01 -0000	2.154
+++ choose.cc	12 Apr 2010 20:32:16 -0000
@@ -131,6 +131,7 @@ ChooserPage::~ChooserPage ()
 void
 ChooserPage::createListview ()
 {
+  SetBusy ();
   static std::vector<packagemeta *> empty_cat;
   static Category dummy_cat (std::string ("No packages found."), empty_cat);
   packagedb db;
@@ -153,6 +154,7 @@ ChooserPage::createListview ()
   /* FIXME: do we need to init the desired fields ? */
   static int ta[] = { IDC_CHOOSE_KEEP, IDC_CHOOSE_PREV, IDC_CHOOSE_CURR, IDC_CHOOSE_EXP, 0 };
   rbset (GetHWND (), ta, IDC_CHOOSE_CURR);
+  ClearBusy ();
 }
 
 /* TODO: review ::overrides for possible consolidation */
@@ -233,12 +235,14 @@ ChooserPage::OnInit ()
 {
   CheckDlgButton (GetHWND (), IDC_CHOOSE_HIDE, BST_CHECKED);
 
+  SetBusy ();
   if (source == IDC_SOURCE_DOWNLOAD || source == IDC_SOURCE_CWD)
     packagemeta::ScanDownloadedFiles ();
 
   packagedb db;
   db.setExistence ();
   db.fillMissingCategory ();
+  ClearBusy ();
 
   if (source == IDC_SOURCE_DOWNLOAD)
     setPrompt("Select packages to download ");
@@ -334,6 +338,7 @@ ChooserPage::keepClicked()
 void
 ChooserPage::changeTrust(trusts aTrust)
 {
+  SetBusy ();
   chooser->defaultTrust (aTrust);
   packagedb db;
   db.markUnVisited ();
@@ -342,6 +347,7 @@ ChooserPage::changeTrust(trusts aTrust)
   chooser->refresh();
   PrereqChecker p;
   p.setTrust (aTrust);
+  ClearBusy ();
 }
 
 bool
Index: PickCategoryLine.cc
===================================================================
RCS file: /cvs/cygwin-apps/setup/PickCategoryLine.cc,v
retrieving revision 2.10
diff -p -u -r2.10 PickCategoryLine.cc
--- PickCategoryLine.cc	24 May 2006 13:01:34 -0000	2.10
+++ PickCategoryLine.cc	12 Apr 2010 20:32:16 -0000
@@ -141,9 +141,11 @@ PickCategoryLine::click (int const myrow
 int 
 PickCategoryLine::set_action (packagemeta::_actions action)
 {
+  theView.GetParent ()->SetBusy ();
   current_default = action;
   int accum_diff = 0;
   for (size_t n = 0; n < bucket.size (); n++)
       accum_diff += bucket[n]->set_action (current_default);
+  theView.GetParent ()->ClearBusy ();
   return accum_diff;
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]