OS/2 tests and more
[p5sagit/p5-mst-13.2.git] / os2 / OS2 / Process / Process.pm
CommitLineData
35bc1fdc 1package OS2::localMorphPM;
30500b05 2# use strict;
35bc1fdc 3
30500b05 4sub new {
5 my ($c,$f) = @_;
6 OS2::MorphPM($f);
7 # print STDERR ">>>>>\n";
8 bless [$f], $c
9}
10sub DESTROY {
11 # print STDERR "<<<<<\n";
12 OS2::UnMorphPM(shift->[0])
13}
35bc1fdc 14
760ac839 15package OS2::Process;
16
35bc1fdc 17BEGIN {
18 require Exporter;
30500b05 19 require XSLoader;
35bc1fdc 20 #require AutoLoader;
7f61b687 21
30500b05 22 our @ISA = qw(Exporter);
23 our $VERSION = "1.0";
24 XSLoader::load('OS2::Process', $VERSION);
35bc1fdc 25}
760ac839 26
760ac839 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.
30500b05 30our @EXPORT = qw(
760ac839 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
7f61b687 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
35bc1fdc 63 ppid
64 ppidOf
65 sidOf
66 scrsize
67 scrsize_set
7f61b687 68 process_entry
35bc1fdc 69 process_entries
70 process_hentry
71 process_hentries
72 change_entry
73 change_entryh
30500b05 74 process_hwnd
35bc1fdc 75 Title_set
76 Title
30500b05 77 winTitle_set
78 winTitle
79 swTitle_set
80 bothTitle_set
35bc1fdc 81 WindowText
82 WindowText_set
83 WindowPos
84 WindowPos_set
30500b05 85 hWindowPos
86 hWindowPos_set
35bc1fdc 87 WindowProcess
88 SwitchToProgram
30500b05 89 DesktopWindow
35bc1fdc 90 ActiveWindow
30500b05 91 ActiveWindow_set
35bc1fdc 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
30500b05 115 EnableWindow
116 EnableWindowUpdate
117 IsWindowEnabled
118 IsWindowVisible
119 IsWindowShowing
120 WindowPtr
121 WindowULong
122 WindowUShort
123 SetWindowBits
124 SetWindowPtr
125 SetWindowULong
126 SetWindowUShort
bd60b2b9 127
128 get_title
129 set_title
760ac839 130);
30500b05 131our @EXPORT_OK = qw(
132 ResetWinError
133 MPFROMSHORT
134 MPVOID
135 MPFROMCHAR
136 MPFROM2SHORT
137 MPFROMSH2CH
138 MPFROMLONG
139);
140
141our $AUTOLOAD;
35bc1fdc 142
760ac839 143sub 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
30500b05 148 (my $constname = $AUTOLOAD) =~ s/.*:://;
149 my $val = constant($constname, @_ ? $_[0] : 0);
760ac839 150 if ($! != 0) {
9c024a02 151 if ($! =~ /Invalid/ || $!{EINVAL}) {
30500b05 152 die "Unsupported function $AUTOLOAD"
153 } else {
154 my ($pack,$file,$line) = caller;
760ac839 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
30500b05 163sub 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
176sub 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
760ac839 186# Preloaded methods go here.
187
35bc1fdc 188sub Title () { (process_entry())[0] }
189
190# *Title_set = \&sesmgr_title_set;
191
192sub swTitle_set_sw {
193 my ($title, @sw) = @_;
194 $sw[0] = $title;
195 change_entry(@sw);
196}
197
30500b05 198sub swTitle_set ($) {
35bc1fdc 199 my (@sw) = process_entry();
200 swTitle_set_sw(shift, @sw);
201}
202
203sub winTitle_set_sw {
204 my ($title, @sw) = @_;
205 my $h = OS2::localMorphPM->new(0);
206 WindowText_set $sw[1], $title;
207}
208
30500b05 209sub winTitle_set ($) {
35bc1fdc 210 my (@sw) = process_entry();
211 winTitle_set_sw(shift, @sw);
212}
213
30500b05 214sub winTitle () {
215 my (@sw) = process_entry();
216 my $h = OS2::localMorphPM->new(0);
217 WindowText $sw[1];
218}
219
220sub bothTitle_set ($) {
35bc1fdc 221 my (@sw) = process_entry();
222 my $t = shift;
223 winTitle_set_sw($t, @sw);
224 swTitle_set_sw($t, @sw);
225}
226
30500b05 227sub Title_set ($) {
35bc1fdc 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
236sub process_entry { swentry_expand(process_swentry(@_)) }
237
238our @hentry_fields = qw( title owner_hwnd icon_hwnd
239 owner_phandle owner_pid owner_sid
240 visible nonswitchable jumpable ptype sw_entry );
241
242sub swentry_hexpand ($) {
243 my %h;
244 @h{@hentry_fields} = swentry_expand(shift);
245 \%h;
246}
247
248sub process_hentry { swentry_hexpand(process_swentry(@_)) }
30500b05 249sub process_hwnd { process_hentry()->{owner_hwnd} }
35bc1fdc 250
251my $swentry_size = swentry_size();
252
253sub 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
262sub process_entries () {
263 map [swentry_expand($_)], sw_entries;
264}
265
266sub process_hentries () {
267 map swentry_hexpand($_), sw_entries;
268}
269
270sub change_entry {
271 change_swentry(create_swentry(@_));
272}
273
274sub create_swentryh ($) {
275 my $h = shift;
276 create_swentry(@$h{@hentry_fields});
277}
278
279sub change_entryh ($) {
280 change_swentry(create_swentryh(shift));
281}
282
283# Massage entries into the same order as WindowPos_set:
284sub WindowPos ($) {
30500b05 285 my ($fl, $h, $w, $y, $x, $behind, $hwnd, @rest)
35bc1fdc 286 = unpack 'L l4 L4', WindowSWP(shift);
287 ($x, $y, $fl, $w, $h, $behind, @rest);
288}
289
30500b05 290# Put them into a hash
291sub 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
298my @SWP_keys = ( [qw(width height)], # SWP_SIZE=1
299 [qw(x y)], # SWP_MOVE=2
300 [qw(behind)] ); # SWP_ZORDER=3
301my %SWP_def;
302@SWP_def{ map @$_, @SWP_keys } = (0) x 20;
303
304# Get them from a hash
305sub 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
328sub ChildWindows (;$) {
329 my $hm = OS2::localMorphPM->new(0);
35bc1fdc 330 my @kids;
30500b05 331 my $h = BeginEnumWindows(@_ ? shift : 1); # HWND_DESKTOP
35bc1fdc 332 my $w;
333 push @kids, $w while $w = GetNextWindow $h;
334 EndEnumWindows $h;
335 @kids;
336}
7f61b687 337
bd60b2b9 338# backward compatibility
339*set_title = \&Title_set;
340*get_title = \&Title;
341
760ac839 342# Autoload methods go after __END__, and are processed by the autosplit program.
343
3441;
345__END__
346
347=head1 NAME
348
35bc1fdc 349OS2::Process - exports constants for system() call, and process control on OS2.
760ac839 350
351=head1 SYNOPSIS
352
353 use OS2::Process;
35bc1fdc 354 $pid = system(P_PM | P_BACKGROUND, "epm.exe");
760ac839 355
356=head1 DESCRIPTION
357
35bc1fdc 358=head2 Optional argument to system()
359
760ac839 360the builtin function system() under OS/2 allows an optional first
361argument which denotes the mode of the process. Note that this argument is
362recognized only if it is strictly numerical.
363
364You 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
372and 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
7f61b687 389=head2 Access to process properties
390
35bc1fdc 391On OS/2 processes have the usual I<parent/child> semantic;
392additionally, there is a hierarchy of sessions with their own
393I<parent/child> tree. A session is either a FS session, or a windowed
394pseudo-session created by PM. A session is a "unit of user
395interaction", a change to in/out settings in one of them does not
396affect other sessions.
7f61b687 397
88c28ceb 398=over
7f61b687 399
35bc1fdc 400=item my_type()
401
402returns 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)>
7f61b687 406
407returns the type of the executable file C<file>, or
408dies on error. The bits 0-2 of the result contain one of the values
409
88c28ceb 410=over
7f61b687 411
412=item C<T_NOTSPEC> (0)
413
35bc1fdc 414Application type is not specified in the executable header.
7f61b687 415
416=item C<T_NOTWINDOWCOMPAT> (1)
417
35bc1fdc 418Application type is not-window-compatible.
7f61b687 419
420=item C<T_WINDOWCOMPAT> (2)
421
35bc1fdc 422Application type is window-compatible.
7f61b687 423
424=item C<T_WINDOWAPI> (3)
425
426Application type is window-API.
427
428=back
429
430The remaining bits should be masked with the following values to
431determine the type of the executable:
432
88c28ceb 433=over
7f61b687 434
435=item C<T_BOUND> (8)
436
437Set to 1 if the executable file has been "bound" (by the BIND command)
438as a Family API application. Bits 0, 1, and 2 still apply.
439
440=item C<T_DLL> (0x10)
441
442Set to 1 if the executable file is a dynamic link library (DLL)
443module. Bits 0, 1, 2, 3, and 5 will be set to 0.
444
445=item C<T_DOS> (0x20)
446
447Set to 1 if the executable file is in PC/DOS format. Bits 0, 1, 2, 3,
448and 4 will be set to 0.
449
450=item C<T_PHYSDRV> (0x40)
451
35bc1fdc 452Set to 1 if the executable file is a physical device driver.
7f61b687 453
454=item C<T_VIRTDRV> (0x80)
455
35bc1fdc 456Set to 1 if the executable file is a virtual device driver.
7f61b687 457
458=item C<T_PROTDLL> (0x100)
459
460Set to 1 if the executable file is a protected-memory dynamic link
461library module.
462
463=item C<T_32BIT> (0x4000)
464
35bc1fdc 465Set to 1 for 32-bit executable files.
7f61b687 466
467=back
468
469file_type() may croak with one of the strings C<"Invalid EXE
470signature"> or C<"EXE marked invalid"> to indicate typical error
471conditions. If given non-absolute path, will look on C<PATH>, will
472add extention F<.exe> if no extension is present (add extension F<.>
473to suppress).
474
35bc1fdc 475=item C<@list = process_codepages()>
476
477the first element is the currently active codepage, up to 2 additional
478entries specify the system's "prepared codepages": the codepages the
479user can switch to. The active codepage of a process is one of the
480prepared codepages of the system (if present).
481
482=item C<process_codepage_set($cp)>
483
484sets the currently active codepage. [Affects printer output, in/out
485codepages of sessions started by this process, and the default
486codepage for drawing in PM; is inherited by kids. Does not affect the
487out- and in-codepages of the session.]
488
489=item ppid()
490
491returns the PID of the parent process.
492
493=item C<ppidOf($pid = $$)>
494
495returns the PID of the parent process of $pid. -1 on error.
496
497=item C<sidOf($pid = $$)>
498
499returns the session id of the process id $pid. -1 on error.
500
501=back
502
503=head2 Control of VIO sessions
504
505VIO applications are applications running in a text-mode session.
506
507=over
508
509=item out_codepage()
510
511gets code page used for screen output (glyphs). -1 means that a user font
512was loaded.
513
514=item C<out_codepage_set($cp)>
515
516sets code page used for screen output (glyphs). -1 switches to a preloaded
517user font. -2 switches off the preloaded user font.
518
519=item in_codepage()
520
521gets code page used for keyboard input. 0 means that a hardware codepage
522is used.
523
524=item C<in_codepage_set($cp)>
525
526sets code page used for keyboard input.
527
528=item C<($w, $h) = scrsize()>
529
530width and height of the given console window in character cells.
531
532=item C<scrsize_set([$w, ] $h)>
533
534set height (and optionally width) of the given console window in
535character cells. Use 0 size to keep the old size.
536
537=item C<($s, $e, $w, $a) = cursor()>
538
539gets 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
541values mean visible, in graphic modes color).
542
543=item C<cursor_set($s, $e, [$w [, $a]])>
544
545sets start/end lines of the blinking cursor in the charcell. Negative
546values mean percents of the character cell height.
547
548=item screen()
549
550gets a buffer with characters and attributes of the screen.
551
552=item C<screen_set($buffer)>
553
554restores the screen given the result of screen().
555
556=back
557
558=head2 Control of the process list
559
560With the exception of Title_set(), all these calls require that PM is
561running, they would not work under alternative Session Managers.
562
563=over
564
7f61b687 565=item process_entry()
566
567returns a list of the following data:
568
88c28ceb 569=over
7f61b687 570
35bc1fdc 571=item
7f61b687 572
573Title of the process (in the C<Ctrl-Esc> list);
574
35bc1fdc 575=item
7f61b687 576
577window handle of switch entry of the process (in the C<Ctrl-Esc> list);
578
35bc1fdc 579=item
7f61b687 580
581window handle of the icon of the process;
582
35bc1fdc 583=item
7f61b687 584
585process handle of the owner of the entry in C<Ctrl-Esc> list;
586
35bc1fdc 587=item
7f61b687 588
589process id of the owner of the entry in C<Ctrl-Esc> list;
590
35bc1fdc 591=item
7f61b687 592
593session id of the owner of the entry in C<Ctrl-Esc> list;
594
35bc1fdc 595=item
7f61b687 596
597whether visible in C<Ctrl-Esc> list;
598
88c28ceb 599=item
7f61b687 600
601whether item cannot be switched to (note that it is not actually
602grayed in the C<Ctrl-Esc> list));
603
35bc1fdc 604=item
7f61b687 605
606whether participates in jump sequence;
607
35bc1fdc 608=item
7f61b687 609
35bc1fdc 610program type. Possible values are:
7f61b687 611
35bc1fdc 612 PROG_DEFAULT 0
613 PROG_FULLSCREEN 1
614 PROG_WINDOWABLEVIO 2
615 PROG_PM 3
616 PROG_VDM 4
617 PROG_WINDOWEDVDM 7
7f61b687 618
619Although there are several other program types for WIN-OS/2 programs,
620these do not show up in this field. Instead, the PROG_VDM or
621PROG_WINDOWEDVDM program types are used. For instance, for
622PROG_31_STDSEAMLESSVDM, PROG_WINDOWEDVDM is used. This is because all
623the WIN-OS/2 programs run in DOS sessions. For example, if a program
624is a windowed WIN-OS/2 program, it runs in a PROG_WINDOWEDVDM
625session. Likewise, if it's a full-screen WIN-OS/2 program, it runs in
626a PROG_VDM session.
627
35bc1fdc 628=item
629
630switch-entry handle.
88c28ceb 631
7f61b687 632=back
633
35bc1fdc 634Optional arguments: the pid and the window-handle of the application running
635in the OS/2 session to query.
636
637=item process_hentry()
638
639similar 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()
7f61b687 647
35bc1fdc 648similar to process_entry(), but returns a list of array reference for all
649the elements in the switch list (one controlling C<Ctrl-Esc> window).
650
651=item process_hentries()
652
653similar to process_hentry(), but returns a list of hash reference for all
654the elements in the switch list (one controlling C<Ctrl-Esc> window).
655
656=item change_entry()
657
658changes a process entry, arguments are the same as process_entry() returns.
659
660=item change_entryh()
661
662Similar to change_entry(), but takes a hash reference as an argument.
663
30500b05 664=item process_hwnd()
665
666returns the C<owner_hwnd> of the process entry (for VIO windowed processes
667this is the frame window of the session).
668
35bc1fdc 669=item Title()
670
30500b05 671returns 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
673implementation is a shortcut via process_entry().)
35bc1fdc 674
675=item C<Title_set(newtitle)>
676
677tries two different interfaces. The Session Manager one does not work
678with some windows (if the title is set from the start).
7f61b687 679This is a limitation of OS/2, in such a case $^E is set to 372 (type
680
681 help 372
682
35bc1fdc 683for a funny - and wrong - explanation ;-). In such cases a
30500b05 684direct-manipulation of low-level entries is used (same as bothTitle_set()).
685Keep in mind that some versions of OS/2 leak memory with such a manipulation.
686
687=item winTitle()
688
689returns text of the titlebar of the current process' window.
690
691=item C<winTitle_set(newtitle)>
692
693sets text of the titlebar of the current process' window. The change does not
694affect the text of the switch entry of the current window.
695
696=item C<swTitle_set(newtitle)>
697
698sets text of the task switch menu entry of the current process' window. [There
699is no API to query this title.] Does it via SwitchEntry interface,
700not Session manager interface. The change does not affect the text of the
701titlebar of the current window.
702
703=item C<bothTitle_set(newtitle)>
704
705sets text of the titlebar and task switch menu of the current process' window
706via direct manipulation of the windows' texts.
35bc1fdc 707
708=item C<SwitchToProgram($sw_entry)>
709
710switch to session given by a switch list handle.
711
712Use of this function causes another window (and its related windows)
713of a PM session to appear on the front of the screen, or a switch to
714another session in the case of a non-PM program. In either case,
715the keyboard (and mouse for the non-PM case) input is directed to
716the new program.
717
718=back
719
720=head2 Control of the PM windows
721
722Some of these API's require sending a message to the specified window.
723In such a case the process needs to be a PM process, or to be morphed
724to a PM process via OS2::MorphPM().
725
726For a temporary morphing to PM use L<OS2::localMorphPM class>.
727
728Keep in mind that PM windows are engaged in 2 "orthogonal" window
729trees, as well as in the z-order list.
730
731One tree is given by the I<parent/child> relationship. This
732relationship affects drawing (child is drawn relative to its parent
733(lower-left corner), and the drawing is clipped by the parent's
734boundary; parent may request that I<it's> drawing is clipped to be
735confined to the outsize of the childs and/or siblings' windows);
736hiding; minimizing/restoring; and destroying windows.
737
738Another tree (not necessarily connected?) is given by I<ownership>
739relationship. Ownership relationship assumes cooperation of the
740engaged windows via passing messages on "important events"; e.g.,
741scrollbars send information messages when the "bar" is moved, menus
742send messages when an item is selected; frames
743move/hide/unhide/minimize/restore/change-z-order-of owned frames when
744the owner is moved/etc., and destroy the owned frames (even when these
745frames are not descendants) when the owner is destroyed; etc. [An
746important restriction on ownership is that owner should be created by
747the same thread as the owned thread, so they engage in the same
748message queue.]
749
30500b05 750Windows may be in many different state: Focused (take keyboard events) or not,
751Activated (=Frame windows in the I<parent/child> tree between the root and
752the window with the focus; usually indicate such "active state" by titlebar
753highlights, and take mouse events) or not, Enabled/Disabled (this influences
754the ability to update the graphic, and may change appearance, as for
755enabled/disabled buttons), Visible/Hidden, Minimized/Maximized/Restored, Modal
756or not, etc.
757
758The APIs below all die() on error with the message being $^E.
35bc1fdc 759
760=over
761
762=item C<WindowText($hwnd)>
763
30500b05 764gets "a text content" of a window. Requires (morphing to) PM.
35bc1fdc 765
766=item C<WindowText_set($hwnd, $text)>
767
30500b05 768sets "a text content" of a window. Requires (morphing to) PM.
35bc1fdc 769
30500b05 770=item C<($x, $y, $flags, $width, $height, $behind, @rest) = WindowPos($hwnd)>
35bc1fdc 771
772gets window position info as 8 integers (of C<SWP>), in the order suitable
30500b05 773for WindowPos_set(). @rest is marked as "reserved" in PM docs. $flags
774is a combination of C<SWP_*> constants.
775
776=item C<$hash = hWindowPos($hwnd)>
777
778gets window position info as a hash reference; the keys are C<flags width
779height x y behind hwnd reserved1 reserved2>.
35bc1fdc 780
30500b05 781Example:
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)>
35bc1fdc 786
787Set state of the window: position, size, zorder, show/hide, activation,
788minimize/maximize/restore etc. Which of these operations to perform
789is governed by $flags.
790
30500b05 791=item C<hWindowPos_set($hash, [$hwnd])>
35bc1fdc 792
30500b05 793Same as C<WindowPos_set>, but takes the position from keys C<fl width height
794x y behind hwnd> of the hash referenced by $hash. If $hwnd is explicitly
795specified, it overrides C<$hash->{hwnd}>. If $hash->{flags} is not specified,
796it is calculated basing on the existing keys of $hash. Requires (morphing to) PM.
35bc1fdc 797
30500b05 798Example:
35bc1fdc 799
30500b05 800 hWindowPos_set {flags => SWP_MAXIMIZE}, $hwnd; # Maximize
801
802=item C<($pid, $tid) = WindowProcess($hwnd)>
803
804gets I<PID> and I<TID> of the process associated to the window.
35bc1fdc 805
806=item C<ClassName($hwnd)>
807
808returns the class name of the window.
809
810If this window is of any of the preregistered WC_* classes the class
811name returned is in the form "#nnnnn", where "nnnnn" is a group
812of up to five digits that corresponds to the value of the WC_* class name
813constant.
814
815=item FocusWindow()
816
30500b05 817returns the handle of the focus window. Optional argument for specifying
818the desktop to use.
35bc1fdc 819
820=item C<FocusWindow_set($hwnd)>
821
822set the focus window by handle. Optional argument for specifying the desktop
823to use. E.g, the first entry in program_entries() is the C<Ctrl-Esc> list.
30500b05 824To show an application, use either one of
35bc1fdc 825
30500b05 826 WinShowWindow( $hwnd, 1 );
827 SetFocus( $hwnd );
828 SwitchToProgram($switch_handle);
35bc1fdc 829
30500b05 830(Which work with alternative focus-to-front policies?) Requires (morphing to) PM.
831
832=item C<ActiveWindow([$parentHwnd])>
833
834gets the active subwindow's handle for $parentHwnd or desktop.
835Returns FALSE if none.
836
837=item C<ActiveWindow_set($hwnd, [$parentHwnd])>
838
839sets the active subwindow's handle for $parentHwnd or desktop. Requires (morphing to) PM.
35bc1fdc 840
841=item C<ShowWindow($hwnd [, $show])>
842
843Set visible/hidden flag of the window. Default: $show is TRUE.
844
30500b05 845=item C<EnableWindowUpdate($hwnd [, $update])>
846
847Set window visibility state flag for the window for subsequent drawing.
848No actual drawing is done at this moment. Use C<ShowWindow($hwnd, $state)>
849when redrawing is needed. While update is disabled, changes to the "window
850state" 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
856Set the window enabled state. Default: $enable is TRUE.
857
858Results in C<WM_ENABLED> message sent to the window. Typically, this
859would change the appearence of the window. If at the moment of disabling
860focus is in the window (or a descendant), focus is lost (no focus anywhere).
861If focus is needed, it can be reassigned explicitly later.
862
863=item IsWindowEnabled(), IsWindowVisible(), IsWindowShowing()
864
865these functions take $hwnd as an argument. IsWindowEnabled() queries
866the state changed by EnableWindow(), IsWindowVisible() the state changed
867by ShowWindow(), IsWindowShowing() is true if there is a part of the window
868visible on the screen.
869
35bc1fdc 870=item C<PostMsg($hwnd, $msg, $mp1, $mp2)>
871
872post message to a window. The meaning of $mp1, $mp2 is specific for each
30500b05 873message 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;
35bc1fdc 894
30500b05 895In fact, MPFROMSHORT() may be omited above.
35bc1fdc 896
30500b05 897For messages to other processes, messages which take/return a pointer are
898not supported.
35bc1fdc 899
30500b05 900=item C<MP*()>
35bc1fdc 901
30500b05 902The functions MPFROMSHORT(), MPVOID(), MPFROMCHAR(), MPFROM2SHORT(),
903MPFROMSH2CH(), MPFROMLONG() can be used the same way as from C. Use them
904to construct parameters $m1, $m2 to PostMsg().
905
906These functions are not exported by default.
35bc1fdc 907
908=item C<$eh = BeginEnumWindows($hwnd)>
909
910starts enumerating immediate child windows of $hwnd in z-order. The
911enumeration reflects the state at the moment of BeginEnumWindows() calls;
30500b05 912use IsWindow() to be sure. All the functions in this group require (morphing to) PM.
35bc1fdc 913
914=item C<$kid_hwnd = GetNextWindow($eh)>
915
916gets the next kid in the list. Gets 0 on error or when the list ends.
7f61b687 917
35bc1fdc 918=item C<EndEnumWindows($eh)>
7f61b687 919
35bc1fdc 920End enumeration and release the list.
921
30500b05 922=item C<@list = ChildWindows([$hwnd])>
35bc1fdc 923
924returns the list of child windows at the moment of the call. Same remark
30500b05 925as for enumeration interface applies. Defaults to HWND_DESKTOP.
926Example of usage:
35bc1fdc 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
937true if the window handle is still valid.
938
939=item C<QueryWindow($hwnd, $type)>
940
941gets the handle of a related window. $type should be one of C<QW_*> constants.
942
943=item C<IsChild($hwnd, $parent)>
944
945return TRUE if $hwnd is a descendant of $parent.
946
947=item C<WindowFromId($hwnd, $id)>
948
949return 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
958gets a handle of a child of $hwndParent at C<($x,$y)>. If $descedantsToo
30500b05 959(defaulting to 1) then children of children may be returned too. May return
35bc1fdc 960$hwndParent (defaults to desktop) if no suitable children are found,
961or 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
967gets a dialog item window handle for an item of type $type of $dlgHwnd
968relative to $relativeHwnd, which is descendant of $dlgHwnd.
969$relativeHwnd may be specified if $type is EDI_FIRSTTABITEM or
970EDI_LASTTABITEM.
971
972The return is always an immediate child of hwndDlg, even if hwnd is
973not an immediate child window. $type may be
974
975=over
976
977=item EDI_FIRSTGROUPITEM
978
979First item in the same group.
980
981=item EDI_FIRSTTABITEM
982
983First item in dialog with style WS_TABSTOP. hwnd is ignored.
984
985=item EDI_LASTGROUPITEM
986
987Last item in the same group.
988
989=item EDI_LASTTABITEM
990
991Last item in dialog with style WS_TABSTOP. hwnd is ignored.
992
993=item EDI_NEXTGROUPITEM
994
995Next item in the same group. Wraps around to beginning of group when
996the end of the group is reached.
997
998=item EDI_NEXTTABITEM
999
1000Next item with style WS_TABSTOP. Wraps around to beginning of dialog
1001item list when end is reached.
1002
1003=item EDI_PREVGROUPITEM
1004
1005Previous item in the same group. Wraps around to end of group when the
1006start of the group is reached. For information on the WS_GROUP style,
1007see Window Styles.
1008
1009=item EDI_PREVTABITEM
1010
1011Previous item with style WS_TABSTOP. Wraps around to end of dialog
1012item list when beginning is reached.
7f61b687 1013
1014=back
1015
30500b05 1016=item ResetWinError()
1017
1018Resets $^E. One may need to call it before the C<Win*>-class APIs which may
1019return 0 during normal operation. In such a case one should check both
1020for return value being zero and $^E being non-zero. The following APIs
1021do ResetWinError() themselves, thus do not need an explicit one:
1022
1023 WindowPtr
1024 WindowULong
1025 WindowUShort
1026 WindowTextLength
1027 ActiveWindow
1028 PostMsg
1029
1030This function is normally not needed. Not exported by default.
1031
35bc1fdc 1032=back
1033
1034=head1 OS2::localMorphPM class
1035
30500b05 1036This class morphs the process to PM for the duration of the given scope.
35bc1fdc 1037
1038 {
1039 my $h = OS2::localMorphPM->new(0);
1040 # Do something
1041 }
1042
1043The argument has the same meaning as one to OS2::MorphPM(). Calls can
1044nest with internal ones being NOPs.
1045
1046=head1 TODO
1047
30500b05 1048Add tests for:
35bc1fdc 1049
30500b05 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
1075Document:
1076Query/SetWindowULong/Short/Ptr, SetWindowBits.
1077
1078Implement InvalidateRect,
1079CreateFrameControl. ClipbrdFmtInfo, ClipbrdData, OpenClipbrd, CloseClipbrd,
1080ClipbrdData_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);
35bc1fdc 1219
30500b05 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;
35bc1fdc 1226
30500b05 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
1240Why C<hWindowPos DesktopWindow> gives C<< behind => HWND_TOP >>?
35bc1fdc 1241
1242=head1 $^E
1243
1244the majority of the APIs of this module set $^E on failure (no matter
1245whether they die() on failure or not). By the semantic of PM API
1246which returns something other than a boolean, it is impossible to
1247distinguish failure from a "normal" 0-return. In such cases C<$^E ==
12480> indicates an absence of error.
1249
30500b05 1250=head1 EXPORTS
1251
1252In addition to symbols described above, the following constants (available
1253also via module C<OS2::Process::Const>) are exportable. Note that these
1254symbols live in package C<OS2::Process::Const>, they are not available
1255by 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
35bc1fdc 1281=head1 BUGS
1282
1283whether a given API dies or returns FALSE/empty-list on error may be
1284confusing. This may change in the future.
1285
760ac839 1286=head1 AUTHOR
1287
35bc1fdc 1288Andreas Kaiser <ak@ananke.s.bawue.de>,
7f61b687 1289Ilya Zakharevich <ilya@math.ohio-state.edu>.
760ac839 1290
1291=head1 SEE ALSO
1292
35bc1fdc 1293C<spawn*>() system calls, L<OS2::Proc> and L<OS2::WinObject> modules.
760ac839 1294
1295=cut