Delivered-To: garrigue at math.nagoya-u.ac.jp Authentication-Results: mailhost.math.nagoya-u.ac.jp sender=lablgtk-bounces at yquem.inria.fr; domainkey=neutral (no query protocol specified; no policy for yquem.inria.fr) Delivered-To: lablgtk at yquem.inria.fr DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:date:from:to:cc:subject :message-id:in-reply-to:references:x-mailer:mime-version :content-type:content-transfer-encoding; bh=jbBMAES787hcw0jDNSnJTgv9R+e8c+hgctHJUWIfzxU=; b=seC1zUzXpzLPOl1uftQkYKa/jJ1Tu+aGwt4oAqRHoZTNGAWYK4fqd/yAV6YrecHKem nEYvHN0X0iSRc7yPhxYlx/210NiuDiHb4GJeNJQrJVGwbKRpR5TTKben99voQk2nOYjr JaR8on4bo3a7s+9Tjcm4O8BD4JvEGz3fDUCDw= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=date:from:to:cc:subject:message-id:in-reply-to:references:x-mailer :mime-version:content-type:content-transfer-encoding; b=wp4zzoIforOWr7koCtPrA21pKRxqzNtfsORZEa3tM2xlc+OaZ+QCsPvMEhZ5Msn4l8 H4dRma0qty9dJY6cw5pCYzyqjdL7Ff0xbx2ygagazZICHza513IXZLb2SPXNlDPi6Xy0 wlQ8JewgIcz9CTjaUE2TTxUmrFsy6d5JsRnlc= Date: Thu, 7 Jan 2010 15:46:24 -0600 From: Peter Groves To: Basile STARYNKEVITCH Subject: Re: [Lablgtk] drawing area & events Message-Id: <20100107154624.d8b70f8c.pdgroves at gmail.com> In-Reply-To: <4B464B1B.4070701 at starynkevitch.net> References: <4B464B1B.4070701 at starynkevitch.net> Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Cc: lablgtk at yquem.inria.fr It's been a while since I dealt with the same issue, so the details are a little hazy, but here are some things I can glean from my code that does pretty much what you're looking for: 0) The general technique was to put my drawing_area in something called a Gbin.event_box, which contains a GObj.event_ops that has it's own methods to add events and connect to it's event streams. Everything below is what it looks like in my code: 1) I wasn't able to use the drawing_area directly to get key events, instead all my code calls a Gobj.event_ops to get key events such as this code that tries to capture if alt, ctrl or shift are depressed and returns them as my own "KeyEmitter" which had the API I needed for my app. The event_ops is associated with an event_box, which in turn contains my drawing_area. I will show my examples of those in (2) and (3) below: ############################################################################## let fromEventOps (gEventOps:GObj.event_ops) = begin let pressedPipe = Pipe.create () in let releasedPipe = Pipe.create () in (** translates for gtk key type to local tKey option. None if the gtk key is not shift, alt, ctrl *) gEventOps#add [`KEY_PRESS]; let translateKey = fun gkey -> begin match gkey with |ky when (ky = GdkKeysyms._Alt_L) -> Some(Alt) |ky when (ky = GdkKeysyms._Shift_L) -> Some(Shift) |ky when (ky = GdkKeysyms._Control_L) -> Some(Ctrl) |_ -> None end in ignore (gEventOps#connect#key_press ~callback:(fun gEvent -> begin (*log Debug (lazy("KeyEmitter: gtk key_press callback begin"));*) let gkey = GdkEvent.Key.keyval gEvent in begin match (translateKey gkey) with |None -> () |Some(ky) -> Pipe.handleEvent pressedPipe ky end; false end)); gEventOps#add [`KEY_RELEASE]; ignore (gEventOps#connect#key_release ~callback:(fun gEvent -> begin (*log Debug (lazy("KeyEmitter: gtk key_release callback begin"));*) let gkey = GdkEvent.Key.keyval gEvent in begin match (translateKey gkey) with |None -> () |Some(ky) -> Pipe.handleEvent releasedPipe ky end; false end)); create ~pressedPipe:pressedPipe ~releasedPipe:releasedPipe end *############################################################################ 2) My drawing_area is in an event_box. Here is my code where that is created and calls the code in (1). I'm not sure what everything does, but it's is in there b/c it was needed to get things to work: ###################################### (** binds a key emitter to a Gtk Event Box *) let makeKeyEmitter (eventBox:GBin.event_box) mouseEmitter = begin (** needed so the event box receives key events, not just the toplevel window*) eventBox#misc#set_can_focus true; let enterMon = fun () -> begin eventBox#misc#grab_focus () end in Pipe.register (MouseEmitter.enteredFlare mouseEmitter) enterMon; KeyEmitter.fromEventOps (eventBox#event) end ##################################### 3) Finally, to call the code in (2) you need an Gbin.event_box, which I produced as below. Note that the 'childWidget' below ends up being a drawing_area: #################################### let create ~childPane = begin let childWidget = FPane.toGWidget childPane in let eventBox = GBin.event_box () in eventBox#add childWidget; ##################################### I hope that gets you on the right track and I'm sorry it's not a self contained example... it's just the code I have lying around. Let me know if you want any more explanation. Peter On Thu, 07 Jan 2010 21:59:07 +0100 Basile STARYNKEVITCH wrote: > Hello All, > > I am fluent in Ocaml, but new to LablGtk (and still scared of OCaml > object system). > > As an exercise, I want to make a drawing area which captures every > mouse click and make a polygon of them, until any key is pressed on > the keyboard. So I coded the following example. > > ##################################### > > (*** > file testdrawar.ml to compile with: > /usr/bin/ocamlopt -I +lablgtk2 -g -annot lablgtk.cmxa > gtkInit.cmx testdrawar.ml -o testdrawar ***) > > let pointslist = ref ([20,60; 20,40; 40,70] : (int * int) list);; > > let drawfun (drawar : GMisc.drawing_area) = > Printf.eprintf "drawfun %d points\n%!" (List.length !pointslist); > let drawindow = > let dmisc = drawar#misc in dmisc#window > in > let drawing = > new GDraw.drawable drawindow > in > drawing#polygon ~filled:false !pointslist; > () > ;; > > let buttonfun bev = > let butnum = GdkEvent.Button.button bev > and x = (int_of_float (GdkEvent.Button.x bev)) > and y = (int_of_float (GdkEvent.Button.x bev)) > in > Printf.eprintf "buttonfun butnum=%d x=%d y=%d\n%!" butnum x y; > pointslist := (x,y)::!pointslist; > () > ;; > > let keyfun kev = > let strk = GdkEvent.Key.string kev in > Printf.eprintf "keyfun %S\n%!" strk; > pointslist := [] > ;; > > > let topwin = GWindow.window ~title: "testdrawar" ~width: 400 ~height: > 300 () in let drawar = GMisc.drawing_area ~packing: topwin#add () in > ignore (drawar#event#add [ `BUTTON_PRESS; `KEY_PRESS]); > ignore (drawar#event#connect#button_press > ~callback: (fun bev -> buttonfun bev; drawfun drawar; > true)); ignore (drawar#event#connect#key_press > ~callback: (fun kev -> keyfun kev; drawfun drawar; > true)); ignore (drawar#event#connect#expose ~callback: (fun ev -> > drawfun drawar; true)); let dmisc = drawar#misc in dmisc#realize (); > topwin#show () > ;; > > GMain.Main.main ();; > > (*eof*) > > ############################################# > > unfortunately, the code above is incorrect: > > For some reason, keyboard events are not caught properly. Should I > ask for focus? > > For some reason, the mouse click coordinates are not correct in the > drawing area. I should make some conversion (how to do that)? > > Any help is appreciated. For the mightly LablGtk contributors, feel > free to add a similar example to the documentation. It would help a > lot. > > Happy New Year 2010 (and Merry Christmas to those celebrating it > today, e.g. in Russia). > > Regards. > > -- > Basile STARYNKEVITCH http://starynkevitch.net/Basile/ > email: basilestarynkevitchnet mobile: +33 6 8501 2359 > 8, rue de la Faiencerie, 92340 Bourg La Reine, France > *** opinions {are only mines, sont seulement les miennes} *** > > _______________________________________________ > Lablgtk mailing list > Lablgtk@yquem.inria.fr > http://yquem.inria.fr/cgi-bin/mailman/listinfo/lablgtk _______________________________________________ Lablgtk mailing list Lablgtk@yquem.inria.fr http://yquem.inria.fr/cgi-bin/mailman/listinfo/lablgtk