Use a GTK+ main loop, generate events in a thread
This commit is contained in:
		
							
								
								
									
										58
									
								
								wdmtg.vala
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								wdmtg.vala
									
									
									
									
									
								
							@@ -37,6 +37,7 @@ namespace Wdmtg {
 | 
				
			|||||||
// --- Globals -----------------------------------------------------------------
 | 
					// --- Globals -----------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  X.Display dpy;                        ///< X display handle
 | 
					  X.Display dpy;                        ///< X display handle
 | 
				
			||||||
 | 
					  int sync_base;                        ///< Sync extension base
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  X.ID idle_counter;                    ///< XSync IDLETIME counter
 | 
					  X.ID idle_counter;                    ///< XSync IDLETIME counter
 | 
				
			||||||
  X.Sync.Value idle_timeout;            ///< User idle timeout
 | 
					  X.Sync.Value idle_timeout;            ///< User idle timeout
 | 
				
			||||||
@@ -218,6 +219,28 @@ namespace Wdmtg {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void generate_events () {
 | 
				
			||||||
 | 
					    var channel = new IOChannel.unix_new (dpy.connection_number ());
 | 
				
			||||||
 | 
					    var watch = channel.create_watch (IOCondition.IN);
 | 
				
			||||||
 | 
					    watch.set_callback (() => {
 | 
				
			||||||
 | 
					      X.Event ev = {0};
 | 
				
			||||||
 | 
					      while (0 != dpy.pending ()) {
 | 
				
			||||||
 | 
					        if (0 != dpy.next_event (ref ev)) {
 | 
				
			||||||
 | 
					          exit_fatal ("XNextEvent returned non-zero");
 | 
				
			||||||
 | 
					        } else if (ev.type == X.EventType.PropertyNotify) {
 | 
				
			||||||
 | 
					          on_x_property_notify (&ev.xproperty);
 | 
				
			||||||
 | 
					        } else if (ev.type == sync_base + X.Sync.EventType.AlarmNotify) {
 | 
				
			||||||
 | 
					          on_x_alarm_notify ((X.Sync.AlarmNotifyEvent *) (&ev));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return true;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var loop = new MainLoop (MainContext.get_thread_default ());
 | 
				
			||||||
 | 
					    watch.attach (loop.get_context ());
 | 
				
			||||||
 | 
					    loop.run ();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool show_version;
 | 
					  bool show_version;
 | 
				
			||||||
  const OptionEntry[] options = {
 | 
					  const OptionEntry[] options = {
 | 
				
			||||||
    { "version", 'V', OptionFlags.IN_MAIN, OptionArg.NONE, ref show_version,
 | 
					    { "version", 'V', OptionFlags.IN_MAIN, OptionArg.NONE, ref show_version,
 | 
				
			||||||
@@ -232,13 +255,11 @@ namespace Wdmtg {
 | 
				
			|||||||
      exit_fatal ("locale not supported by Xlib");
 | 
					      exit_fatal ("locale not supported by Xlib");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      var ctx = new OptionContext (" - activity tracker");
 | 
					      Gtk.init_with_args (ref args, " - activity tracker", options, null);
 | 
				
			||||||
      ctx.set_help_enabled (true);
 | 
					 | 
				
			||||||
      ctx.add_main_entries (options, null);
 | 
					 | 
				
			||||||
      ctx.parse (ref args);
 | 
					 | 
				
			||||||
    } catch (OptionError e) {
 | 
					    } catch (OptionError e) {
 | 
				
			||||||
      exit_fatal ("option parsing failed: %s", e.message);
 | 
					      exit_fatal ("option parsing failed: %s", e.message);
 | 
				
			||||||
      return 1;
 | 
					    } catch (Error e) {
 | 
				
			||||||
 | 
					      exit_fatal ("%s", e.message);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (show_version) {
 | 
					    if (show_version) {
 | 
				
			||||||
      stdout.printf (Config.PROJECT_NAME + " " + Config.PROJECT_VERSION + "\n");
 | 
					      stdout.printf (Config.PROJECT_NAME + " " + Config.PROJECT_VERSION + "\n");
 | 
				
			||||||
@@ -258,7 +279,7 @@ namespace Wdmtg {
 | 
				
			|||||||
    //   by polling the XScreenSaverInfo::idle field, see
 | 
					    //   by polling the XScreenSaverInfo::idle field, see
 | 
				
			||||||
    //   https://www.x.org/releases/X11R7.5/doc/man/man3/Xss.3.html
 | 
					    //   https://www.x.org/releases/X11R7.5/doc/man/man3/Xss.3.html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int sync_base, dummy;
 | 
					    int dummy;
 | 
				
			||||||
    if (0 == X.Sync.query_extension (dpy, out sync_base, out dummy)
 | 
					    if (0 == X.Sync.query_extension (dpy, out sync_base, out dummy)
 | 
				
			||||||
     || 0 == X.Sync.initialize (dpy, out dummy, out dummy))
 | 
					     || 0 == X.Sync.initialize (dpy, out dummy, out dummy))
 | 
				
			||||||
      exit_fatal ("cannot initialize XSync");
 | 
					      exit_fatal ("cannot initialize XSync");
 | 
				
			||||||
@@ -336,26 +357,11 @@ namespace Wdmtg {
 | 
				
			|||||||
    if ((rc = db.exec ("COMMIT", null, out errmsg)) != Sqlite.OK)
 | 
					    if ((rc = db.exec ("COMMIT", null, out errmsg)) != Sqlite.OK)
 | 
				
			||||||
      exit_fatal ("%s: %s", db_path, errmsg);
 | 
					      exit_fatal ("%s: %s", db_path, errmsg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var loop = new MainLoop ();
 | 
					    var generator = new Thread<void> ("generator", generate_events);
 | 
				
			||||||
    var channel = new IOChannel.unix_new (dpy.connection_number ());
 | 
					    // TODO: somehow read events from the async queue
 | 
				
			||||||
    channel.add_watch (IOCondition.IN, (source, condition) => {
 | 
					    // TODO: listen for connections on the control socket
 | 
				
			||||||
      if (0 == (condition & IOCondition.IN))
 | 
					    Gtk.main ();
 | 
				
			||||||
        return true;
 | 
					    generator.join ();
 | 
				
			||||||
 | 
					 | 
				
			||||||
      X.Event ev = {0};
 | 
					 | 
				
			||||||
      while (0 != dpy.pending ()) {
 | 
					 | 
				
			||||||
        if (0 != dpy.next_event (ref ev)) {
 | 
					 | 
				
			||||||
          exit_fatal ("XNextEvent returned non-zero");
 | 
					 | 
				
			||||||
        } else if (ev.type == X.EventType.PropertyNotify) {
 | 
					 | 
				
			||||||
          on_x_property_notify (&ev.xproperty);
 | 
					 | 
				
			||||||
        } else if (ev.type == sync_base + X.Sync.EventType.AlarmNotify) {
 | 
					 | 
				
			||||||
          on_x_alarm_notify ((X.Sync.AlarmNotifyEvent *) (&ev));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    loop.run ();
 | 
					 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user