OS/2 tests and more
[p5sagit/p5-mst-13.2.git] / os2 / OS2 / Process / Process.pm
1 package OS2::localMorphPM;
2 # use strict;
3
4 sub new {
5   my ($c,$f) = @_;
6   OS2::MorphPM($f);
7   # print STDERR ">>>>>\n";
8   bless [$f], $c
9 }
10 sub DESTROY {
11   # print STDERR "<<<<<\n";
12   OS2::UnMorphPM(shift->[0])
13 }
14
15 package OS2::Process;
16
17 BEGIN {
18   require Exporter;
19   require XSLoader;
20   #require AutoLoader;
21
22   our @ISA = qw(Exporter);
23   our $VERSION = "1.0";
24   XSLoader::load('OS2::Process', $VERSION);
25 }
26
27 # Items to export into callers namespace by default. Note: do not export
28 # names by default without a very good reason. Use EXPORT_OK instead.
29 # Do not simply export all your public functions/methods/constants.
30 our @EXPORT = qw(
31         P_BACKGROUND
32         P_DEBUG
33         P_DEFAULT
34         P_DETACH
35         P_FOREGROUND
36         P_FULLSCREEN
37         P_MAXIMIZE
38         P_MINIMIZE
39         P_NOCLOSE
40         P_NOSESSION
41         P_NOWAIT
42         P_OVERLAY
43         P_PM
44         P_QUOTE
45         P_SESSION
46         P_TILDE
47         P_UNRELATED
48         P_WAIT
49         P_WINDOWED
50         my_type
51         file_type
52         T_NOTSPEC
53         T_NOTWINDOWCOMPAT
54         T_WINDOWCOMPAT
55         T_WINDOWAPI
56         T_BOUND
57         T_DLL
58         T_DOS
59         T_PHYSDRV
60         T_VIRTDRV
61         T_PROTDLL
62         T_32BIT
63         ppid
64         ppidOf
65         sidOf
66         scrsize
67         scrsize_set
68         process_entry
69         process_entries
70         process_hentry
71         process_hentries
72         change_entry
73         change_entryh
74         process_hwnd
75         Title_set
76         Title
77         winTitle_set
78         winTitle
79         swTitle_set
80         bothTitle_set
81         WindowText
82         WindowText_set
83         WindowPos
84         WindowPos_set
85         hWindowPos
86         hWindowPos_set
87         WindowProcess
88         SwitchToProgram
89         DesktopWindow
90         ActiveWindow
91         ActiveWindow_set
92         ClassName
93         FocusWindow
94         FocusWindow_set
95         ShowWindow
96         PostMsg
97         BeginEnumWindows
98         EndEnumWindows
99         GetNextWindow
100         IsWindow
101         ChildWindows
102         out_codepage
103         out_codepage_set
104         in_codepage
105         in_codepage_set
106         cursor
107         cursor_set
108         screen
109         screen_set
110         process_codepages
111         QueryWindow
112         WindowFromId
113         WindowFromPoint
114         EnumDlgItem
115         EnableWindow
116         EnableWindowUpdate
117         IsWindowEnabled
118         IsWindowVisible
119         IsWindowShowing
120         WindowPtr
121         WindowULong
122         WindowUShort
123         SetWindowBits
124         SetWindowPtr
125         SetWindowULong
126         SetWindowUShort
127
128         get_title
129         set_title
130 );
131 our @EXPORT_OK = qw(
132         ResetWinError
133         MPFROMSHORT
134         MPVOID
135         MPFROMCHAR
136         MPFROM2SHORT
137         MPFROMSH2CH
138         MPFROMLONG
139 );
140
141 our $AUTOLOAD;
142
143 sub AUTOLOAD {
144     # This AUTOLOAD is used to 'autoload' constants from the constant()
145     # XS function.  If a constant is not found then control is passed
146     # to the AUTOLOAD in AutoLoader.
147
148     (my $constname = $AUTOLOAD) =~ s/.*:://;
149     my $val = constant($constname, @_ ? $_[0] : 0);
150     if ($! != 0) {
151         if ($! =~ /Invalid/ || $!{EINVAL}) {
152             die "Unsupported function $AUTOLOAD"
153         } else {
154             my ($pack,$file,$line) = caller;
155             die "Your vendor has not defined OS2::Process macro $constname, used at $file line $line.
156 ";
157         }
158     }
159     eval "sub $AUTOLOAD { $val }";
160     goto &$AUTOLOAD;
161 }
162
163 sub const_import {
164   require OS2::Process::Const;
165   my $sym = shift;
166   my ($err, $val) = OS2::Process::Const::constant($sym);
167   die $err if $err;
168   my $p = caller(1);
169
170   # no strict;
171
172   *{"$p\::$sym"} = sub () { $val };
173   ();                   # needed by import()
174 }
175
176 sub import {
177   my $class = shift;
178   my $ini = @_;
179   @_ = ($class,
180         map {
181           /^(HWND|WM|SC|SWP|WC|PROG|QW|EDI|WS|QWS|QWP|QWL|FF|FI|LS|FS|FCF|BS|MS|TBM|CF|CFI|FID)_/ ? const_import($_) : $_
182         } @_);
183   goto &Exporter::import if @_ > 1 or $ini == 0;
184 }
185
186 # Preloaded methods go here.
187
188 sub Title () { (process_entry())[0] }
189
190 # *Title_set = \&sesmgr_title_set;
191
192 sub swTitle_set_sw {
193   my ($title, @sw) = @_;
194   $sw[0] = $title;
195   change_entry(@sw);
196 }
197
198 sub swTitle_set ($) {
199   my (@sw) = process_entry();
200   swTitle_set_sw(shift, @sw);
201 }
202
203 sub winTitle_set_sw {
204   my ($title, @sw) = @_;
205   my $h = OS2::localMorphPM->new(0);
206   WindowText_set $sw[1], $title;
207 }
208
209 sub winTitle_set ($) {
210   my (@sw) = process_entry();
211   winTitle_set_sw(shift, @sw);
212 }
213
214 sub winTitle () {
215   my (@sw) = process_entry();
216   my $h = OS2::localMorphPM->new(0);
217   WindowText $sw[1];
218 }
219
220 sub bothTitle_set ($) {
221   my (@sw) = process_entry();
222   my $t = shift;
223   winTitle_set_sw($t, @sw);
224   swTitle_set_sw($t, @sw);
225 }
226
227 sub Title_set ($) {
228   my $t = shift;
229   return 1 if sesmgr_title_set($t);
230   return 0 unless $^E == 372;
231   my (@sw) = process_entry();
232   winTitle_set_sw($t, @sw);
233   swTitle_set_sw($t, @sw);
234 }
235
236 sub process_entry { swentry_expand(process_swentry(@_)) }
237
238 our @hentry_fields = qw( title owner_hwnd icon_hwnd 
239                          owner_phandle owner_pid owner_sid
240                          visible nonswitchable jumpable ptype sw_entry );
241
242 sub swentry_hexpand ($) {
243   my %h;
244   @h{@hentry_fields} = swentry_expand(shift);
245   \%h;
246 }
247
248 sub process_hentry { swentry_hexpand(process_swentry(@_)) }
249 sub process_hwnd { process_hentry()->{owner_hwnd} }
250
251 my $swentry_size = swentry_size();
252
253 sub sw_entries () {
254   my $s = swentries_list();
255   my ($c, $s1) = unpack 'La*', $s;
256   die "Unconsistent size in swentries_list()" unless 4+$c*$swentry_size == length $s;
257   my (@l, $e);
258   push @l, $e while $e = substr $s1, 0, $swentry_size, '';
259   @l;
260 }
261
262 sub process_entries () {
263   map [swentry_expand($_)], sw_entries;
264 }
265
266 sub process_hentries () {
267   map swentry_hexpand($_), sw_entries;
268 }
269
270 sub change_entry {
271   change_swentry(create_swentry(@_));
272 }
273
274 sub create_swentryh ($) {
275   my $h = shift;
276   create_swentry(@$h{@hentry_fields});
277 }
278
279 sub change_entryh ($) {
280   change_swentry(create_swentryh(shift));
281 }
282
283 # Massage entries into the same order as WindowPos_set:
284 sub WindowPos ($) {
285   my ($fl, $h, $w, $y, $x, $behind, $hwnd, @rest)
286         = unpack 'L l4 L4', WindowSWP(shift);
287   ($x, $y, $fl, $w, $h, $behind, @rest);
288 }
289
290 # Put them into a hash
291 sub hWindowPos ($) {
292   my %h;
293   @h{ qw(flags height width y x behind hwnd reserved1 reserved2) }
294         = unpack 'L l4 L4', WindowSWP(shift);
295   \%h;
296 }
297
298 my @SWP_keys = ( [qw(width height)],    # SWP_SIZE=1
299                  [qw(x y)],             # SWP_MOVE=2
300                  [qw(behind)] );        # SWP_ZORDER=3
301 my %SWP_def;
302 @SWP_def{ map @$_, @SWP_keys }  = (0) x 20;
303
304 # Get them from a hash
305 sub hWindowPos_set ($$) {
306   my $hash = shift;
307   my $hwnd = (@_ ? shift : $hash->{hwnd} );
308   my $flags;
309   if (exists $hash->{flags}) {
310     $flags = $hash->{flags};
311   } else {                      # Set flags according to existing keys in $hash
312     $flags = 0;
313     for my $bit (0..2) {
314       exists $hash->{$_} and $flags |= (1<<$bit) for @{$SWP_keys[$bit]};
315     }
316   }
317   for my $bit (0..2) {          # Check for required keys
318     next unless $flags & (1<<$bit);
319     exists $hash->{$_}
320       or die sprintf "key $_ required for flags=%#x", $flags
321         for @{$SWP_keys[$bit]};
322   }
323   my %h = (%SWP_def, flags => $flags, %$hash);          # Avoid warnings
324   my ($x, $y, $fl, $w, $h, $behind) = @h{ qw(x y flags width height behind) };
325   WindowPos_set($hwnd, $x, $y, $fl, $w, $h, $behind);
326 }
327
328 sub ChildWindows (;$) {
329   my $hm = OS2::localMorphPM->new(0);
330   my @kids;
331   my $h = BeginEnumWindows(@_ ? shift : 1);     # HWND_DESKTOP
332   my $w;
333   push @kids, $w while $w = GetNextWindow $h;
334   EndEnumWindows $h;
335   @kids;
336 }
337
338 # backward compatibility
339 *set_title = \&Title_set;
340 *get_title = \&Title;
341
342 # Autoload methods go after __END__, and are processed by the autosplit program.
343
344 1;
345 __END__
346
347 =head1 NAME
348
349 OS2::Process - exports constants for system() call, and process control on OS2.
350
351 =head1 SYNOPSIS
352
353     use OS2::Process;
354     $pid = system(P_PM | P_BACKGROUND, "epm.exe");
355
356 =head1 DESCRIPTION
357
358 =head2 Optional argument to system()
359
360 the builtin function system() under OS/2 allows an optional first
361 argument which denotes the mode of the process. Note that this argument is
362 recognized only if it is strictly numerical.
363
364 You can use either one of the process modes:
365
366         P_WAIT (0)      = wait until child terminates (default)
367         P_NOWAIT        = do not wait until child terminates
368         P_SESSION       = new session
369         P_DETACH        = detached
370         P_PM            = PM program
371
372 and optionally add PM and session option bits:
373
374         P_DEFAULT (0)   = default
375         P_MINIMIZE      = minimized
376         P_MAXIMIZE      = maximized
377         P_FULLSCREEN    = fullscreen (session only)
378         P_WINDOWED      = windowed (session only)
379
380         P_FOREGROUND    = foreground (if running in foreground)
381         P_BACKGROUND    = background
382
383         P_NOCLOSE       = don't close window on exit (session only)
384
385         P_QUOTE         = quote all arguments
386         P_TILDE         = MKS argument passing convention
387         P_UNRELATED     = do not kill child when father terminates
388
389 =head2 Access to process properties
390
391 On OS/2 processes have the usual I<parent/child> semantic;
392 additionally, there is a hierarchy of sessions with their own
393 I<parent/child> tree.  A session is either a FS session, or a windowed
394 pseudo-session created by PM.  A session is a "unit of user
395 interaction", a change to in/out settings in one of them does not
396 affect other sessions.
397
398 =over
399
400 =item my_type()
401
402 returns the type of the current process (one of
403 "FS", "DOS", "VIO", "PM", "DETACH" and "UNKNOWN"), or C<undef> on error.
404
405 =item C<file_type(file)>
406
407 returns the type of the executable file C<file>, or
408 dies on error.  The bits 0-2 of the result contain one of the values
409
410 =over
411
412 =item C<T_NOTSPEC> (0)
413
414 Application type is not specified in the executable header.
415
416 =item C<T_NOTWINDOWCOMPAT> (1)
417
418 Application type is not-window-compatible.
419
420 =item C<T_WINDOWCOMPAT> (2)
421
422 Application type is window-compatible.
423
424 =item C<T_WINDOWAPI> (3)
425
426 Application type is window-API.
427
428 =back
429
430 The remaining bits should be masked with the following values to
431 determine the type of the executable:
432
433 =over
434
435 =item C<T_BOUND> (8)
436
437 Set to 1 if the executable file has been "bound" (by the BIND command)
438 as a Family API application. Bits 0, 1, and 2 still apply.
439
440 =item C<T_DLL> (0x10)
441
442 Set to 1 if the executable file is a dynamic link library (DLL)
443 module. Bits 0, 1, 2, 3, and 5 will be set to 0.
444
445 =item C<T_DOS> (0x20)
446
447 Set to 1 if the executable file is in PC/DOS format. Bits 0, 1, 2, 3,
448 and 4 will be set to 0.
449
450 =item C<T_PHYSDRV> (0x40)
451
452 Set to 1 if the executable file is a physical device driver.
453
454 =item C<T_VIRTDRV> (0x80)
455
456 Set to 1 if the executable file is a virtual device driver.
457
458 =item C<T_PROTDLL> (0x100)
459
460 Set to 1 if the executable file is a protected-memory dynamic link
461 library module.
462
463 =item C<T_32BIT> (0x4000)
464
465 Set to 1 for 32-bit executable files.
466
467 =back
468
469 file_type() may croak with one of the strings C<"Invalid EXE
470 signature"> or C<"EXE marked invalid"> to indicate typical error
471 conditions.  If given non-absolute path, will look on C<PATH>, will
472 add extention F<.exe> if no extension is present (add extension F<.>
473 to suppress).
474
475 =item C<@list = process_codepages()>
476
477 the first element is the currently active codepage, up to 2 additional
478 entries specify the system's "prepared codepages": the codepages the
479 user can switch to.  The active codepage of a process is one of the
480 prepared codepages of the system (if present).
481
482 =item C<process_codepage_set($cp)>
483
484 sets the currently active codepage.  [Affects printer output, in/out
485 codepages of sessions started by this process, and the default
486 codepage for drawing in PM; is inherited by kids.  Does not affect the
487 out- and in-codepages of the session.]
488
489 =item ppid()
490
491 returns the PID of the parent process.
492
493 =item C<ppidOf($pid = $$)>
494
495 returns the PID of the parent process of $pid.  -1 on error.
496
497 =item C<sidOf($pid = $$)>
498
499 returns the session id of the process id $pid.  -1 on error.
500
501 =back
502
503 =head2 Control of VIO sessions
504
505 VIO applications are applications running in a text-mode session.
506
507 =over
508
509 =item out_codepage()
510
511 gets code page used for screen output (glyphs).  -1 means that a user font
512 was loaded.
513
514 =item C<out_codepage_set($cp)>
515
516 sets code page used for screen output (glyphs).  -1 switches to a preloaded
517 user font.  -2 switches off the preloaded user font.
518
519 =item in_codepage()
520
521 gets code page used for keyboard input.  0 means that a hardware codepage
522 is used.
523
524 =item C<in_codepage_set($cp)>
525
526 sets code page used for keyboard input.
527
528 =item C<($w, $h) = scrsize()>
529
530 width and height of the given console window in character cells.
531
532 =item C<scrsize_set([$w, ] $h)>
533
534 set height (and optionally width) of the given console window in
535 character cells.  Use 0 size to keep the old size.
536
537 =item C<($s, $e, $w, $a) = cursor()>
538
539 gets start/end lines of the blinking cursor in the charcell, its width
540 (1 on text modes) and attribute (-1 for hidden, in text modes other
541 values mean visible, in graphic modes color).
542
543 =item C<cursor_set($s, $e, [$w [, $a]])>
544
545 sets start/end lines of the blinking cursor in the charcell.  Negative
546 values mean percents of the character cell height.
547
548 =item screen()
549
550 gets a buffer with characters and attributes of the screen.
551
552 =item C<screen_set($buffer)>
553
554 restores the screen given the result of screen().
555
556 =back
557
558 =head2 Control of the process list
559
560 With the exception of Title_set(), all these calls require that PM is
561 running, they would not work under alternative Session Managers.
562
563 =over
564
565 =item process_entry()
566
567 returns a list of the following data:
568
569 =over
570
571 =item
572
573 Title of the process (in the C<Ctrl-Esc> list);
574
575 =item
576
577 window handle of switch entry of the process (in the C<Ctrl-Esc> list);
578
579 =item
580
581 window handle of the icon of the process;
582
583 =item
584
585 process handle of the owner of the entry in C<Ctrl-Esc> list;
586
587 =item
588
589 process id of the owner of the entry in C<Ctrl-Esc> list;
590
591 =item
592
593 session id of the owner of the entry in C<Ctrl-Esc> list;
594
595 =item
596
597 whether visible in C<Ctrl-Esc> list;
598
599 =item
600
601 whether item cannot be switched to (note that it is not actually
602 grayed in the C<Ctrl-Esc> list));
603
604 =item
605
606 whether participates in jump sequence;
607
608 =item
609
610 program type.  Possible values are:
611
612      PROG_DEFAULT                       0
613      PROG_FULLSCREEN                    1
614      PROG_WINDOWABLEVIO                 2
615      PROG_PM                            3
616      PROG_VDM                           4
617      PROG_WINDOWEDVDM                   7
618
619 Although there are several other program types for WIN-OS/2 programs,
620 these do not show up in this field. Instead, the PROG_VDM or
621 PROG_WINDOWEDVDM program types are used. For instance, for
622 PROG_31_STDSEAMLESSVDM, PROG_WINDOWEDVDM is used. This is because all
623 the WIN-OS/2 programs run in DOS sessions. For example, if a program
624 is a windowed WIN-OS/2 program, it runs in a PROG_WINDOWEDVDM
625 session. Likewise, if it's a full-screen WIN-OS/2 program, it runs in
626 a PROG_VDM session.
627
628 =item
629
630 switch-entry handle.
631
632 =back
633
634 Optional arguments: the pid and the window-handle of the application running
635 in the OS/2 session to query.
636
637 =item process_hentry()
638
639 similar to process_entry(), but returns a hash reference, the keys being
640
641   title owner_hwnd icon_hwnd owner_phandle owner_pid owner_sid
642   visible nonswitchable jumpable ptype sw_entry
643
644 (a copy of the list of keys is in @hentry_fields).
645
646 =item process_entries()
647
648 similar to process_entry(), but returns a list of array reference for all
649 the elements in the switch list (one controlling C<Ctrl-Esc> window).
650
651 =item process_hentries()
652
653 similar to process_hentry(), but returns a list of hash reference for all
654 the elements in the switch list (one controlling C<Ctrl-Esc> window).
655
656 =item change_entry()
657
658 changes a process entry, arguments are the same as process_entry() returns.
659
660 =item change_entryh()
661
662 Similar to change_entry(), but takes a hash reference as an argument.
663
664 =item process_hwnd()
665
666 returns the C<owner_hwnd> of the process entry (for VIO windowed processes
667 this is the frame window of the session).
668
669 =item Title()
670
671 returns the text of the task switch menu entry of the current session.
672 (There is no way to get this info in non-standard Session Managers.  This
673 implementation is a shortcut via process_entry().)
674
675 =item C<Title_set(newtitle)>
676
677 tries two different interfaces.  The Session Manager one does not work
678 with some windows (if the title is set from the start).
679 This is a limitation of OS/2, in such a case $^E is set to 372 (type
680
681   help 372
682
683 for a funny - and wrong  - explanation ;-).  In such cases a
684 direct-manipulation of low-level entries is used (same as bothTitle_set()).
685 Keep in mind that some versions of OS/2 leak memory with such a manipulation.
686
687 =item winTitle()
688
689 returns text of the titlebar of the current process' window.
690
691 =item C<winTitle_set(newtitle)>
692
693 sets text of the titlebar of the current process' window.  The change does not
694 affect the text of the switch entry of the current window.
695
696 =item C<swTitle_set(newtitle)>
697
698 sets text of the task switch menu entry of the current process' window.  [There
699 is no API to query this title.]  Does it via SwitchEntry interface,
700 not Session manager interface.  The change does not affect the text of the
701 titlebar of the current window.
702
703 =item C<bothTitle_set(newtitle)>
704
705 sets text of the titlebar and task switch menu of the current process' window
706 via direct manipulation of the windows' texts.
707
708 =item C<SwitchToProgram($sw_entry)>
709
710 switch to session given by a switch list handle.
711
712 Use of this function causes another window (and its related windows)
713 of a PM session to appear on the front of the screen, or a switch to
714 another session in the case of a non-PM program. In either case,
715 the keyboard (and mouse for the non-PM case) input is directed to
716 the new program.
717
718 =back
719
720 =head2 Control of the PM windows
721
722 Some of these API's require sending a message to the specified window.
723 In such a case the process needs to be a PM process, or to be morphed
724 to a PM process via OS2::MorphPM().
725
726 For a temporary morphing to PM use L<OS2::localMorphPM class>.
727
728 Keep in mind that PM windows are engaged in 2 "orthogonal" window
729 trees, as well as in the z-order list.
730
731 One tree is given by the I<parent/child> relationship.  This
732 relationship affects drawing (child is drawn relative to its parent
733 (lower-left corner), and the drawing is clipped by the parent's
734 boundary; parent may request that I<it's> drawing is clipped to be
735 confined to the outsize of the childs and/or siblings' windows);
736 hiding; minimizing/restoring; and destroying windows.
737
738 Another tree (not necessarily connected?) is given by I<ownership>
739 relationship.  Ownership relationship assumes cooperation of the
740 engaged windows via passing messages on "important events"; e.g.,
741 scrollbars send information messages when the "bar" is moved, menus
742 send messages when an item is selected; frames
743 move/hide/unhide/minimize/restore/change-z-order-of owned frames when
744 the owner is moved/etc., and destroy the owned frames (even when these
745 frames are not descendants) when the owner is destroyed; etc.  [An
746 important restriction on ownership is that owner should be created by
747 the same thread as the owned thread, so they engage in the same
748 message queue.]
749
750 Windows may be in many different state: Focused (take keyboard events) or not,
751 Activated (=Frame windows in the I<parent/child> tree between the root and
752 the window with the focus; usually indicate such "active state" by titlebar
753 highlights, and take mouse events) or not, Enabled/Disabled (this influences
754 the ability to update the graphic, and may change appearance, as for 
755 enabled/disabled buttons), Visible/Hidden, Minimized/Maximized/Restored, Modal
756 or not, etc.
757
758 The APIs below all die() on error with the message being $^E.
759
760 =over
761
762 =item C<WindowText($hwnd)>
763
764 gets "a text content" of a window.  Requires (morphing to) PM.
765
766 =item C<WindowText_set($hwnd, $text)>
767
768 sets "a text content" of a window.  Requires (morphing to) PM.
769
770 =item C<($x, $y, $flags, $width, $height, $behind, @rest) = WindowPos($hwnd)>
771
772 gets window position info as 8 integers (of C<SWP>), in the order suitable
773 for WindowPos_set().  @rest is marked as "reserved" in PM docs.  $flags
774 is a combination of C<SWP_*> constants.
775
776 =item C<$hash = hWindowPos($hwnd)>
777
778 gets window position info as a hash reference; the keys are C<flags width
779 height x y behind hwnd reserved1 reserved2>.
780
781 Example:
782
783   exit unless $hash->{flags} & SWP_MAXIMIZE;    # Maximized
784
785 =item C<WindowPos_set($hwnd, $x, $y, $flags = SWP_MOVE, $width = 0, $height = 0, $behind = HWND_TOP)>
786
787 Set state of the window: position, size, zorder, show/hide, activation,
788 minimize/maximize/restore etc.  Which of these operations to perform
789 is governed by $flags.
790
791 =item C<hWindowPos_set($hash, [$hwnd])>
792
793 Same as C<WindowPos_set>, but takes the position from keys C<fl width height
794 x y behind hwnd> of the hash referenced by $hash.  If $hwnd is explicitly
795 specified, it overrides C<$hash->{hwnd}>.  If $hash->{flags} is not specified,
796 it is calculated basing on the existing keys of $hash.  Requires (morphing to) PM.
797
798 Example:
799
800   hWindowPos_set {flags => SWP_MAXIMIZE}, $hwnd; # Maximize
801
802 =item C<($pid, $tid) = WindowProcess($hwnd)>
803
804 gets I<PID> and I<TID> of the process associated to the window.
805
806 =item C<ClassName($hwnd)>
807
808 returns the class name of the window.
809
810 If this window is of any of the preregistered WC_* classes the class
811 name returned is in the form "#nnnnn", where "nnnnn" is a group
812 of up to five digits that corresponds to the value of the WC_* class name
813 constant.
814
815 =item FocusWindow()
816
817 returns the handle of the focus window.  Optional argument for specifying
818 the desktop to use.
819
820 =item C<FocusWindow_set($hwnd)>
821
822 set the focus window by handle.  Optional argument for specifying the desktop
823 to use.  E.g, the first entry in program_entries() is the C<Ctrl-Esc> list.
824 To show an application, use either one of
825
826        WinShowWindow( $hwnd, 1 );
827        SetFocus( $hwnd );
828        SwitchToProgram($switch_handle);
829
830 (Which work with alternative focus-to-front policies?)  Requires (morphing to) PM.
831
832 =item C<ActiveWindow([$parentHwnd])>
833
834 gets the active subwindow's handle for $parentHwnd or desktop.
835 Returns FALSE if none.
836
837 =item C<ActiveWindow_set($hwnd, [$parentHwnd])>
838
839 sets the active subwindow's handle for $parentHwnd or desktop.  Requires (morphing to) PM.
840
841 =item C<ShowWindow($hwnd [, $show])>
842
843 Set visible/hidden flag of the window.  Default: $show is TRUE.
844
845 =item C<EnableWindowUpdate($hwnd [, $update])>
846
847 Set window visibility state flag for the window for subsequent drawing.
848 No actual drawing is done at this moment.  Use C<ShowWindow($hwnd, $state)>
849 when redrawing is needed.  While update is disabled, changes to the "window
850 state" do not change the appearence of the window.  Default: $update is TRUE.
851
852 (What is manipulated is the bit C<WS_VISIBLE> of the window style.)
853
854 =item C<EnableWindow($hwnd [, $enable])>
855
856 Set the window enabled state.  Default: $enable is TRUE.
857
858 Results in C<WM_ENABLED> message sent to the window.  Typically, this
859 would change the appearence of the window.  If at the moment of disabling
860 focus is in the window (or a descendant), focus is lost (no focus anywhere).
861 If focus is needed, it can be reassigned explicitly later.
862
863 =item IsWindowEnabled(), IsWindowVisible(), IsWindowShowing()
864
865 these functions take $hwnd as an argument.  IsWindowEnabled() queries
866 the state changed by EnableWindow(), IsWindowVisible() the state changed
867 by ShowWindow(), IsWindowShowing() is true if there is a part of the window
868 visible on the screen.
869
870 =item C<PostMsg($hwnd, $msg, $mp1, $mp2)>
871
872 post message to a window.  The meaning of $mp1, $mp2 is specific for each
873 message id $msg, they default to 0.  E.g.,
874
875   use OS2::Process qw(:DEFAULT WM_SYSCOMMAND WM_CONTEXTMENU
876                       WM_SAVEAPPLICATION WM_QUIT WM_CLOSE
877                       SC_MAXIMIZE SC_RESTORE);
878   $hwnd = process_hentry()->{owner_hwnd};
879   # Emulate choosing `Restore' from the window menu:
880   PostMsg $hwnd, WM_SYSCOMMAND, MPFROMSHORT(SC_RESTORE); # Not immediate
881
882   # Emulate `Show-Contextmenu' (Double-Click-2), two ways:
883   PostMsg ActiveWindow, WM_CONTEXTMENU;
884   PostMsg FocusWindow, WM_CONTEXTMENU;
885
886   /* Emulate `Close' */
887   PostMsg ActiveWindow, WM_CLOSE;
888
889   /* Same but with some "warnings" to the application */
890   $hwnd = ActiveWindow;
891   PostMsg $hwnd, WM_SAVEAPPLICATION;
892   PostMsg $hwnd, WM_CLOSE;
893   PostMsg $hwnd, WM_QUIT;
894
895 In fact, MPFROMSHORT() may be omited above.
896
897 For messages to other processes, messages which take/return a pointer are
898 not supported.
899
900 =item C<MP*()>
901
902 The functions MPFROMSHORT(), MPVOID(), MPFROMCHAR(), MPFROM2SHORT(),
903 MPFROMSH2CH(), MPFROMLONG() can be used the same way as from C.  Use them
904 to construct parameters $m1, $m2 to PostMsg().
905
906 These functions are not exported by default.
907
908 =item C<$eh = BeginEnumWindows($hwnd)>
909
910 starts enumerating immediate child windows of $hwnd in z-order.  The
911 enumeration reflects the state at the moment of BeginEnumWindows() calls;
912 use IsWindow() to be sure.  All the functions in this group require (morphing to) PM.
913
914 =item C<$kid_hwnd = GetNextWindow($eh)>
915
916 gets the next kid in the list.  Gets 0 on error or when the list ends.
917
918 =item C<EndEnumWindows($eh)>
919
920 End enumeration and release the list.
921
922 =item C<@list = ChildWindows([$hwnd])>
923
924 returns the list of child windows at the moment of the call.  Same remark
925 as for enumeration interface applies.  Defaults to HWND_DESKTOP.
926 Example of usage:
927
928   sub l {
929     my ($o,$h) = @_;
930     printf ' ' x $o . "%#x\n", $h;
931     l($o+2,$_) for ChildWindows $h;
932   }
933   l 0, $HWND_DESKTOP
934
935 =item C<IsWindow($hwnd)>
936
937 true if the window handle is still valid.
938
939 =item C<QueryWindow($hwnd, $type)>
940
941 gets the handle of a related window.  $type should be one of C<QW_*> constants.
942
943 =item C<IsChild($hwnd, $parent)>
944
945 return TRUE if $hwnd is a descendant of $parent.
946
947 =item C<WindowFromId($hwnd, $id)>
948
949 return a window handle of a child of $hwnd with the given $id.
950
951   hwndSysMenu = WinWindowFromID(hwndDlg, FID_SYSMENU);
952   WinSendMsg(hwndSysMenu, MM_SETITEMATTR,
953       MPFROM2SHORT(SC_CLOSE, TRUE),
954       MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED));
955
956 =item C<WindowFromPoint($x, $y [, $hwndParent [, $descedantsToo]])>
957
958 gets a handle of a child of $hwndParent at C<($x,$y)>.  If $descedantsToo
959 (defaulting to 1) then children of children may be returned too.  May return
960 $hwndParent (defaults to desktop) if no suitable children are found,
961 or 0 if the point is outside the parent.
962
963 $x and $y are relative to $hwndParent.
964
965 =item C<EnumDlgItem($dlgHwnd, $type [, $relativeHwnd])>
966
967 gets a dialog item window handle for an item of type $type of $dlgHwnd
968 relative to $relativeHwnd, which is descendant of $dlgHwnd.
969 $relativeHwnd may be specified if $type is EDI_FIRSTTABITEM or
970 EDI_LASTTABITEM.
971
972 The return is always an immediate child of hwndDlg, even if hwnd is
973 not an immediate child window.  $type may be
974
975 =over
976
977 =item EDI_FIRSTGROUPITEM
978
979 First item in the same group.
980
981 =item EDI_FIRSTTABITEM
982
983 First item in dialog with style WS_TABSTOP. hwnd is ignored.
984
985 =item EDI_LASTGROUPITEM
986
987 Last item in the same group.
988
989 =item EDI_LASTTABITEM
990
991 Last item in dialog with style WS_TABSTOP. hwnd is ignored.
992
993 =item EDI_NEXTGROUPITEM
994
995 Next item in the same group. Wraps around to beginning of group when
996 the end of the group is reached.
997
998 =item EDI_NEXTTABITEM
999
1000 Next item with style WS_TABSTOP. Wraps around to beginning of dialog
1001 item list when end is reached.
1002
1003 =item EDI_PREVGROUPITEM
1004
1005 Previous item in the same group. Wraps around to end of group when the
1006 start of the group is reached. For information on the WS_GROUP style,
1007 see Window Styles.
1008
1009 =item EDI_PREVTABITEM
1010
1011 Previous item with style WS_TABSTOP. Wraps around to end of dialog
1012 item list when beginning is reached.
1013
1014 =back
1015
1016 =item ResetWinError()
1017
1018 Resets $^E.  One may need to call it before the C<Win*>-class APIs which may
1019 return 0 during normal operation.  In such a case one should check both
1020 for return value being zero and $^E being non-zero.  The following APIs
1021 do ResetWinError() themselves, thus do not need an explicit one:
1022
1023   WindowPtr
1024   WindowULong
1025   WindowUShort
1026   WindowTextLength
1027   ActiveWindow
1028   PostMsg
1029
1030 This function is normally not needed.  Not exported by default.
1031
1032 =back
1033
1034 =head1 OS2::localMorphPM class
1035
1036 This class morphs the process to PM for the duration of the given scope.
1037
1038   {
1039     my $h = OS2::localMorphPM->new(0);
1040     # Do something
1041   }
1042
1043 The argument has the same meaning as one to OS2::MorphPM().  Calls can
1044 nest with internal ones being NOPs.
1045
1046 =head1 TODO
1047
1048 Add tests for:
1049
1050         SwitchToProgram
1051         ClassName
1052         out_codepage
1053         out_codepage_set
1054         in_codepage
1055         in_codepage_set
1056         cursor
1057         cursor_set
1058         screen
1059         screen_set
1060         process_codepages
1061         QueryWindow
1062         EnumDlgItem
1063         WindowPtr
1064         WindowULong
1065         WindowUShort
1066         SetWindowBits
1067         SetWindowPtr
1068         SetWindowULong
1069         SetWindowUShort
1070         my_type
1071         file_type
1072         scrsize
1073         scrsize_set
1074
1075 Document:
1076 Query/SetWindowULong/Short/Ptr, SetWindowBits.
1077
1078 Implement InvalidateRect,
1079 CreateFrameControl. ClipbrdFmtInfo, ClipbrdData, OpenClipbrd, CloseClipbrd,
1080 ClipbrdData_set, EnumClipbrdFmt, EmptyClipbrd.  SOMETHINGFROMMR.
1081
1082
1083   >But I wish to change the default button if the user enters some
1084   >text into an entryfield.  I can detect the entry ok, but can't
1085   >seem to get the button to change to default.
1086   >
1087   >No matter what message I send it, it's being ignored.
1088
1089   You need to get the style of the buttons using WinQueryWindowULong/QWL_STYLE,
1090   set and reset the BS_DEFAULT bits as appropriate and then use
1091   WinSetWindowULong/QWL_STYLE to set the button style.
1092   Something like this:
1093     hwnd1 = WinWindowFromID (hwnd, id1);
1094     hwnd2 = WinWindowFromID (hwnd, id2);
1095     style1 = WinQueryWindowULong (hwnd1, QWL_STYLE);
1096     style2 = WinQueryWindowULong (hwnd2, QWL_STYLE);
1097     style1 |= style2 & BS_DEFAULT;
1098     style2 &= ~BS_DEFAULT;
1099     WinSetWindowULong (hwnd1, QWL_STYLE, style1);
1100     WinSetWindowULong (hwnd2, QWL_STYLE, style2);
1101
1102  > How to do query and change a frame creation flags for existing window?
1103
1104  Set the style bits that correspond to the FCF_* flag for the frame
1105  window and then send a WM_UPDATEFRAME message with the appropriate FCF_*
1106  flag in mp1.
1107
1108  ULONG ulFrameStyle;
1109  ulFrameStyle = WinQueryWindowULong( WinQueryWindow(hwnd, QW_PARENT),
1110  QWL_STYLE );
1111  ulFrameStyle = (ulFrameStyle & ~FS_SIZEBORDER) | FS_BORDER;
1112  WinSetWindowULong(   WinQueryWindow(hwnd, QW_PARENT),
1113                       QWL_STYLE,
1114                       ulFrameStyle );
1115  WinSendMsg( WinQueryWindow(hwnd, QW_PARENT),
1116              WM_UPDATEFRAME,
1117              MPFROMP(FCF_SIZEBORDER),
1118              MPVOID );
1119
1120  If the FCF_* flags you want to change does not have a corresponding FS_*
1121  style (i.e. the FCF_* flag corresponds to the presence/lack of a frame
1122  control rather than a property of the frame itself) then you create or
1123  destroy the appropriate control window using the correct FID_* window
1124  identifier and then send the WM_UPDATEFRAME message with the appropriate
1125  FCF_* flag in mp1.
1126
1127  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*
1128   |  SetFrameBorder()                                                          |
1129   |    Changes a frame window's border to the requested type.                  |
1130   |                                                                            |
1131   |  Parameters on entry:                                                      |
1132   |    hwndFrame     -> Frame window whose border is to be changed.            |
1133   |    ulBorderStyle -> Type of border to change to.                           |
1134   |                                                                            |
1135   |  Returns:                                                                  |
1136   |    BOOL          -> Success indicator.                                     |
1137   |                                                                            |
1138   * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
1139  BOOL SetFrameBorder( HWND hwndFrame, ULONG ulBorderType )  {
1140    ULONG  ulFrameStyle;
1141    BOOL   fSuccess = TRUE;
1142
1143    ulFrameStyle = WinQueryWindowULong( hwndFrame, QWL_STYLE );
1144
1145    switch ( ulBorderType )  {
1146      case FS_SIZEBORDER :
1147        ulFrameStyle = (ulFrameStyle & ~(FS_DLGBORDER | FS_BORDER))
1148                       | FS_SIZEBORDER;
1149        break;
1150
1151      case FS_DLGBORDER :
1152        ulFrameStyle = (ulFrameStyle & ~(FS_SIZEBORDER | FS_BORDER))
1153                       | FS_DLGBORDER;
1154        break;
1155
1156      case FS_BORDER :
1157        ulFrameStyle = (ulFrameStyle & ~(FS_SIZEBORDER | FS_DLGBORDER))
1158                       | FS_BORDER;
1159        break;
1160
1161      default :
1162        fSuccess = FALSE;
1163        break;
1164    }  // end switch
1165
1166    if ( fSuccess )  {
1167      fSuccess = WinSetWindowULong( hwndFrame, QWL_STYLE, ulFrameStyle );
1168
1169      if ( fSuccess )  {
1170        fSuccess = (BOOL)WinSendMsg( hwndFrame, WM_UPDATEFRAME, 0, 0 );
1171        if ( fSuccess )
1172          fSuccess = WinInvalidateRect( hwndFrame, NULL, TRUE );
1173      }
1174    }
1175
1176    return ( fSuccess );
1177
1178  }  // End SetFrameBorder()
1179
1180          hwndMenu=WinLoadMenu(hwndParent,NULL,WND_IMAGE);
1181          WinSetWindowUShort(hwndMenu,QWS_ID,FID_MENU);
1182          ulStyle=WinQueryWindowULong(hwndMenu,QWL_STYLE);
1183          WinSetWindowULong(hwndMenu,QWL_STYLE,ulStyle|MS_ACTIONBAR);
1184          WinSendMsg(hwndParent,WM_UPDATEFRAME,MPFROMSHORT(FCF_MENU),0L);
1185
1186   OS/2-windows have another "parent" called the *owner*,
1187   which must be set separately - to get a close relationship:
1188
1189     WinSetOwner (hwndFrameChild, hwndFrameMain);
1190
1191   Now your child should move with your main window!
1192   And always stays on top of it....
1193
1194   To avoid this, for example for dialogwindows, you can
1195   also "disconnect" this relationship with:
1196
1197     WinSetWindowBits (hwndFrameChild, QWL_STYLE
1198                       , FS_NOMOVEWITHOWNER
1199                       , FS_NOMOVEWITHOWNER);
1200
1201  Adding a button icon later:
1202
1203  /* switch the button style to BS_MINIICON */
1204  WinSetWindowBits(hwndBtn, QWL_STYLE, BS_MINIICON, BS_MINIICON) ;
1205
1206  /* set up button control data */
1207  BTNCDATA    bcd;
1208  bcd.cb = sizeof(BTNCDATA);
1209  bcd.hImage = WinLoadPointer(HWND_DESKTOP, dllHandle, ID_ICON_BUTTON1) ;
1210  bcd.fsCheckState = bcd.fsHiliteState = 0 ;
1211
1212
1213  WNDPARAMS   wp;
1214  wp.fsStatus = WPM_CTLDATA;
1215  wp.pCtlData = &bcd;
1216
1217  /* add the icon on the button */
1218  WinSendMsg(hwndBtn, WM_SETWINDOWPARAMS, (MPARAM)&wp, NULL);
1219
1220  MO> Can anyone tell what OS/2 expects of an application to be properly
1221  MO> minimized to the desktop?
1222  case WM MINMAXFRAME :
1223  {
1224    BOOL  fShow = ! (((PSWP) mp1)->fl & SWP MINIMIZE);
1225    HENUM henum;
1226
1227    HWND  hwndChild;
1228
1229    WinEnableWindowUpdate ( hwnd, FALSE );
1230
1231    for (henum=WinBeginEnumWindows(hwnd);
1232         (hwndChild = WinGetNextWindow (henum)) != 0; )
1233    WinShowWindow ( hwndChild, fShow );
1234
1235    WinEndEnumWindows ( henum );
1236    WinEnableWindowUpdate ( hwnd, TRUE );
1237  }
1238  break;
1239
1240 Why C<hWindowPos DesktopWindow> gives C<< behind => HWND_TOP >>?
1241
1242 =head1 $^E
1243
1244 the majority of the APIs of this module set $^E on failure (no matter
1245 whether they die() on failure or not).  By the semantic of PM API
1246 which returns something other than a boolean, it is impossible to
1247 distinguish failure from a "normal" 0-return.  In such cases C<$^E ==
1248 0> indicates an absence of error.
1249
1250 =head1 EXPORTS
1251
1252 In addition to symbols described above, the following constants (available
1253 also via module C<OS2::Process::Const>) are exportable.  Note that these
1254 symbols live in package C<OS2::Process::Const>, they are not available
1255 by full name through C<OS2::Process>!
1256
1257   HWND_*                Standard (abstract) window handles
1258   WM_*                  Message ids
1259   SC_*                  WM_SYSCOMMAND flavor
1260   SWP_*                 Size/move etc flag
1261   WC_*                  Standard window classes
1262   PROG_*                Program category (PM, VIO etc)
1263   QW_*                  Query-Window flag
1264   EDI_*                 Enumerate-Dialog-Item code
1265   WS_*                  Window Style flag
1266   QWS_*                 Query-window-UShort offsets
1267   QWP_*                 Query-window-pointer offsets
1268   QWL_*                 Query-window-ULong offsets
1269   FF_*                  Frame-window state flags
1270   FI_*                  Frame-window information flags
1271   LS_*                  List box styles
1272   FS_*                  Frame style
1273   FCF_*                 Frame creation flags
1274   BS_*                  Button style
1275   MS_*                  Menu style
1276   TBM_*                 Title bar messages?
1277   CF_*                  Clipboard formats
1278   CFI_*                 Clipboard storage type
1279   FID_*                 ids of subwindows of frames
1280
1281 =head1 BUGS
1282
1283 whether a given API dies or returns FALSE/empty-list on error may be
1284 confusing.  This may change in the future.
1285
1286 =head1 AUTHOR
1287
1288 Andreas Kaiser <ak@ananke.s.bawue.de>,
1289 Ilya Zakharevich <ilya@math.ohio-state.edu>.
1290
1291 =head1 SEE ALSO
1292
1293 C<spawn*>() system calls, L<OS2::Proc> and L<OS2::WinObject> modules.
1294
1295 =cut