1 package OS2::localMorphPM;
7 # print STDERR ">>>>>\n";
11 # print STDERR "<<<<<\n";
12 OS2::UnMorphPM(shift->[0])
22 our @ISA = qw(Exporter);
23 our $VERSION = "1.01";
24 XSLoader::load('OS2::Process', $VERSION);
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.
145 FocusWindow_set_keep_Zorder
147 ActiveDesktopPathname
200 # This AUTOLOAD is used to 'autoload' constants from the constant()
201 # XS function. If a constant is not found then control is passed
202 # to the AUTOLOAD in AutoLoader.
204 (my $constname = $AUTOLOAD) =~ s/.*:://;
205 my $val = constant($constname, @_ ? $_[0] : 0);
207 if ($! =~ /Invalid/ || $!{EINVAL}) {
208 die "Unsupported function $AUTOLOAD"
210 my ($pack,$file,$line) = caller;
211 die "Your vendor has not defined OS2::Process macro $constname, used at $file line $line.
215 eval "sub $AUTOLOAD { $val }";
220 require OS2::Process::Const;
222 my ($err, $val) = OS2::Process::Const::constant($sym);
228 *{"$p\::$sym"} = sub () { $val };
229 (); # needed by import()
237 /^(HWND|WM|SC|SWP|WC|PROG|QW|EDI|WS|QWS|QWP|QWL|FF|FI|LS|FS|FCF|BS|MS|TBM|CF|CFI|FID|MB|MBID|CF|CFI|SPTR)_/ ? const_import($_) : $_
239 goto &Exporter::import if @_ > 1 or $ini == 0;
242 # Preloaded methods go here.
244 sub Title () { (process_entry())[0] }
246 # *Title_set = \&sesmgr_title_set;
249 my ($title, @sw) = @_;
254 sub swTitle_set ($) {
255 my (@sw) = process_entry();
256 swTitle_set_sw(shift, @sw);
259 sub winTitle_set_sw {
260 my ($title, @sw) = @_;
261 my $h = OS2::localMorphPM->new(0);
262 WindowText_set $sw[1], $title;
265 sub winTitle_set ($) {
266 my (@sw) = process_entry();
267 winTitle_set_sw(shift, @sw);
271 my (@sw) = process_entry();
272 my $h = OS2::localMorphPM->new(0);
276 sub bothTitle_set ($) {
277 my (@sw) = process_entry();
279 winTitle_set_sw($t, @sw);
280 swTitle_set_sw($t, @sw);
285 return 1 if sesmgr_title_set($t);
286 return 0 unless $^E == 372;
287 my (@sw) = process_entry();
288 winTitle_set_sw($t, @sw);
289 swTitle_set_sw($t, @sw);
292 sub process_entry { swentry_expand(process_swentry(@_)) }
294 our @hentry_fields = qw( title owner_hwnd icon_hwnd
295 owner_phandle owner_pid owner_sid
296 visible nonswitchable jumpable ptype sw_entry );
298 sub swentry_hexpand ($) {
300 @h{@hentry_fields} = swentry_expand(shift);
304 sub process_hentry { swentry_hexpand(process_swentry(@_)) }
305 sub process_hwnd { process_hentry()->{owner_hwnd} }
307 my $swentry_size = swentry_size();
310 my $s = swentries_list();
311 my ($c, $s1) = unpack 'La*', $s;
312 die "Unconsistent size in swentries_list()" unless 4+$c*$swentry_size == length $s;
314 push @l, $e while $e = substr $s1, 0, $swentry_size, '';
318 sub process_entries () {
319 map [swentry_expand($_)], sw_entries;
322 sub process_hentries () {
323 map swentry_hexpand($_), sw_entries;
327 change_swentry(create_swentry(@_));
330 sub create_swentryh ($) {
332 create_swentry(@$h{@hentry_fields});
335 sub change_entryh ($) {
336 change_swentry(create_swentryh(shift));
339 # Massage entries into the same order as WindowPos_set:
341 my ($fl, $h, $w, $y, $x, $behind, $hwnd, @rest)
342 = unpack 'L l4 L4', WindowSWP(shift);
343 ($x, $y, $fl, $w, $h, $behind, @rest);
346 # Put them into a hash
349 @h{ qw(flags height width y x behind hwnd reserved1 reserved2) }
350 = unpack 'L l4 L4', WindowSWP(shift);
354 my @SWP_keys = ( [qw(width height)], # SWP_SIZE=1
355 [qw(x y)], # SWP_MOVE=2
356 [qw(behind)] ); # SWP_ZORDER=3
358 @SWP_def{ map @$_, @SWP_keys } = (0) x 20;
360 # Get them from a hash
361 sub hWindowPos_set ($$) {
363 my $hwnd = (@_ ? shift : $hash->{hwnd} );
365 if (exists $hash->{flags}) {
366 $flags = $hash->{flags};
367 } else { # Set flags according to existing keys in $hash
370 exists $hash->{$_} and $flags |= (1<<$bit) for @{$SWP_keys[$bit]};
373 for my $bit (0..2) { # Check for required keys
374 next unless $flags & (1<<$bit);
376 or die sprintf "key $_ required for flags=%#x", $flags
377 for @{$SWP_keys[$bit]};
379 my %h = (%SWP_def, flags => $flags, %$hash); # Avoid warnings
380 my ($x, $y, $fl, $w, $h, $behind) = @h{ qw(x y flags width height behind) };
381 WindowPos_set($hwnd, $x, $y, $fl, $w, $h, $behind);
384 sub ChildWindows (;$) {
385 my $hm = OS2::localMorphPM->new(0);
387 my $h = BeginEnumWindows(@_ ? shift : 1); # HWND_DESKTOP
389 push @kids, $w while $w = GetNextWindow $h;
395 my $d = DesktopWindow;
398 my $p = QueryWindow $w, 5; # QW_PARENT;
399 return $w if not $p or $p == $d;
404 sub FocusWindow_set_keep_Zorder ($) {
407 my $b = hWindowPos($t)->{behind}; # we are behind this
408 EnableWindowUpdate($t, 0);
410 # sleep 1; # Make flicker stronger when present
411 hWindowPos_set {behind => $b}, $t;
412 EnableWindowUpdate($t, 1);
415 sub ClipbrdText (@) {
416 my $morph = OS2::localMorphPM->new(0);
418 my $txt = unpack 'p', pack 'L', ClipbrdData @_;
423 sub ClipbrdText_set ($;$) {
424 my $morph = OS2::localMorphPM->new(0);
426 EmptyClipbrd(); # It may contain other types
427 my ($txt, $no_convert_nl) = (shift, shift);
428 ClipbrdData_set($txt, !$no_convert_nl, @_);
432 sub MessageBox ($;$$$$$) {
433 my $morph = OS2::localMorphPM->new(0);
434 die "MessageBox needs text" unless @_;
435 push @_ , ($0 eq '-e' ? "Perl one-liner's message" : "$0 message") if @_ == 1;
441 sub get_pointer ($;$$) {
443 return $pointers{$id} if exists $pointers{$id};
444 $pointers{$id} = &SysPointer;
447 # $button needs to be of the form 'String', ['String'] or ['String', flag].
448 # If ['String'], it is assumed the default button; same for 'String' if $only
450 sub process_MB2 ($$;$) {
451 die "process_MB2() needs 2 arguments, got '@_'" unless @_ == 2 or @_ == 3;
452 my ($button, $ret, $only) = @_;
453 # default is BS_PUSHBUTTON, add BS_DEFAULT if $only is set
454 $button = [$button, $only ? 0x400 : 0] unless ref $button eq 'ARRAY';
455 push @$button, 0x400 if @$button == 1; # BS_PUSHBUTTON|BS_DEFAULT
456 die "Button needs to be of the form 'String', ['String'] or ['String', flag]"
457 unless @$button == 2;
458 pack "Z71 x L l", $button->[0], $ret, $button->[1]; # name, retval, flag
461 # If one button, make it the default one even if it is of 'String' => val form.
462 # If icon is of the form 'SP#<number>', load this via SysPointer.
463 sub process_MB2_INFO ($;$$$) {
466 die "process_MB2_INFO() needs 1..4 arguments" unless @_ and @_ < 5;
468 die "Buttons array should consist of pairs" if @$buttons % 2;
470 push @_, 0 unless @_; # Icon id (pointer)
471 # Box flags (MB_MOVABLE and MB_INFORMATION or MB_CUSTOMICON)
472 push @_, ($_[0] ? 0x4080 : 0x4030) unless @_ > 1;
473 push @_, 0 unless @_ > 2; # Notify window
475 my ($icon, $style, $notify) = (shift, shift, shift);
476 $icon = get_pointer $1 if $icon =~ /^SP#(\d+)\z/;
477 $out = pack "L L L L", # icon, #buttons, style, notify, buttons
478 $icon, @$buttons/2, $style, $notify;
480 map process_MB2($buttons->[2*$_], $buttons->[2*$_+1], @$buttons == 2),
482 pack('L', length(pack 'L', 0) + length $out) . $out;
485 # MessageBox2 'Try this', OS2::Process::process_MB2_INFO([['Dismiss', 0] => 0x1000], OS2::Process::get_pointer(22),0x4080,0), 'me', 1, 0, 0
487 # MessageBox2 'Try this', [[['Dismiss', 0] => 0x1000], 'SP#22'], 'me'
488 # 0x80 means MB_CUSTOMICON (does not focus?!). This focuses:
489 # MessageBox2 'Try this', [[['Dismiss',0x400] => 0x1000], 0, 0x4030,0]
490 # 0x400 means BS_DEFAULT. This is the same as the shortcut
491 # MessageBox2 'Try this', [[Dismiss => 0x1000]]
492 sub MessageBox2 ($;$$$$$) {
493 my $morph = OS2::localMorphPM->new(0);
494 die "MessageBox needs text" unless @_;
495 push @_ , [[Dismiss => 0x1000], # Name, retval (BS_PUSHBUTTON|BS_DEFAULT)
496 #0, # get_pointer(11), # SPTR_ICONINFORMATION
497 #0x4030, # MB_MOVEABLE | MB_INFORMATION
498 #0, # Notify window; was 1==HWND_DESKTOP
500 push @_ , ($0 eq '-e' ? "Perl one-liner's message" : "$0's message") if @_ == 2;
501 $_[1] = &process_MB2_INFO(@{$_[1]}) if ref($_[1]) eq 'ARRAY';
505 # backward compatibility
506 *set_title = \&Title_set;
507 *get_title = \&Title;
509 # adapter; display; cbMemory; Configuration; VDHVersion; Flags; HWBufferSize;
510 # FullSaveSize; PartSaveSize; EMAdaptersOFF; EMDisplaysOFF;
511 sub vioConfig (;$$) {
512 my $data = &_vioConfig;
513 my @out = unpack 'x[S]SSLSSSLLLSS', $data;
514 # If present, offset points to S/S (with only the first work making sense)
515 my (@adaptersEMU, @displayEMU);
516 @displaysEMU = unpack("x[$out[10]]S/S", $data), pop @out if @out > 10;
517 @adaptersEMU = unpack("x[$out[ 9]]S/S", $data), pop @out if @out > 9;
518 $out[9] = $adaptersEMU[0] if @adaptersEMU;
519 $out[10] = $displaysEMU[0] if @displaysEMU;
523 my @vioConfig = qw(adapter display cbMemory Configuration VDHVersion Flags
524 HWBufferSize FullSaveSize PartSaveSize EMAdapters EMDisplays);
526 sub viohConfig (;$$) {
528 @h{@vioConfig} = &vioConfig;
532 # fbType; color; col; row; hres; vres; fmt_ID; attrib; buf_addr; buf_length;
533 # full_length; partial_length; ext_data_addr;
534 sub vioMode() {unpack 'x[S]CCSSSSCCLLLLL', _vioMode}
536 my @vioMode = qw( fbType color col row hres vres fmt_ID attrib buf_addr
537 buf_length full_length partial_length ext_data_addr);
541 @h{@vioMode} = vioMode;
546 my %h = (viohMode, @_);
547 my $o = pack 'x[S]CCSSSSCCLLLLL', @h{@vioMode};
548 $o = pack 'SCCSSSSCCLLLLL', length $o, @h{@vioMode};
552 sub kbdChar (;$$) {unpack 'CCCCSL', &_kbdChar}
554 my @kbdChar = qw(ascii scancode status nlsstate shifts time);
557 @h{@kbdChar} = &kbdChar;
561 sub kbdStatus (;$) {unpack 'x[S]SSSS', &_kbdStatus}
562 my @kbdStatus = qw(state turnChar intCharFlags shifts);
563 sub kbdhStatus (;$) {
565 @h{@kbdStatus} = &kbdStatus;
569 my $h = (@_ % 2 ? shift @_ : 0);
570 my %h = (kbdhStatus($h), @_);
571 my $o = pack 'x[S]SSSS', @h{@kbdStatus};
572 $o = pack 'SSSSS', length $o, @h{@kbdStatus};
573 _kbdStatus_set($o,$h);
577 # Autoload methods go after __END__, and are processed by the autosplit program.
584 OS2::Process - exports constants for system() call, and process control on OS2.
589 $pid = system(P_PM | P_BACKGROUND, "epm.exe");
593 =head2 Optional argument to system()
595 the builtin function system() under OS/2 allows an optional first
596 argument which denotes the mode of the process. Note that this argument is
597 recognized only if it is strictly numerical.
599 You can use either one of the process modes:
601 P_WAIT (0) = wait until child terminates (default)
602 P_NOWAIT = do not wait until child terminates
603 P_SESSION = new session
607 and optionally add PM and session option bits:
609 P_DEFAULT (0) = default
610 P_MINIMIZE = minimized
611 P_MAXIMIZE = maximized
612 P_FULLSCREEN = fullscreen (session only)
613 P_WINDOWED = windowed (session only)
615 P_FOREGROUND = foreground (if running in foreground)
616 P_BACKGROUND = background
618 P_NOCLOSE = don't close window on exit (session only)
620 P_QUOTE = quote all arguments
621 P_TILDE = MKS argument passing convention
622 P_UNRELATED = do not kill child when father terminates
624 =head2 Access to process properties
626 On OS/2 processes have the usual I<parent/child> semantic;
627 additionally, there is a hierarchy of sessions with their own
628 I<parent/child> tree. A session is either a FS session, or a windowed
629 pseudo-session created by PM. A session is a "unit of user
630 interaction", a change to in/out settings in one of them does not
631 affect other sessions.
637 returns the type of the current process (one of
638 "FS", "DOS", "VIO", "PM", "DETACH" and "UNKNOWN"), or C<undef> on error.
640 =item C<file_type(file)>
642 returns the type of the executable file C<file>, or
643 dies on error. The bits 0-2 of the result contain one of the values
647 =item C<T_NOTSPEC> (0)
649 Application type is not specified in the executable header.
651 =item C<T_NOTWINDOWCOMPAT> (1)
653 Application type is not-window-compatible.
655 =item C<T_WINDOWCOMPAT> (2)
657 Application type is window-compatible.
659 =item C<T_WINDOWAPI> (3)
661 Application type is window-API.
665 The remaining bits should be masked with the following values to
666 determine the type of the executable:
672 Set to 1 if the executable file has been "bound" (by the BIND command)
673 as a Family API application. Bits 0, 1, and 2 still apply.
675 =item C<T_DLL> (0x10)
677 Set to 1 if the executable file is a dynamic link library (DLL)
678 module. Bits 0, 1, 2, 3, and 5 will be set to 0.
680 =item C<T_DOS> (0x20)
682 Set to 1 if the executable file is in PC/DOS format. Bits 0, 1, 2, 3,
683 and 4 will be set to 0.
685 =item C<T_PHYSDRV> (0x40)
687 Set to 1 if the executable file is a physical device driver.
689 =item C<T_VIRTDRV> (0x80)
691 Set to 1 if the executable file is a virtual device driver.
693 =item C<T_PROTDLL> (0x100)
695 Set to 1 if the executable file is a protected-memory dynamic link
698 =item C<T_32BIT> (0x4000)
700 Set to 1 for 32-bit executable files.
704 file_type() may croak with one of the strings C<"Invalid EXE
705 signature"> or C<"EXE marked invalid"> to indicate typical error
706 conditions. If given non-absolute path, will look on C<PATH>, will
707 add extension F<.exe> if no extension is present (add extension F<.>
710 =item C<@list = process_codepages()>
712 the first element is the currently active codepage, up to 2 additional
713 entries specify the system's "prepared codepages": the codepages the
714 user can switch to. The active codepage of a process is one of the
715 prepared codepages of the system (if present).
717 =item C<process_codepage_set($cp)>
719 sets the currently active codepage. [Affects printer output, in/out
720 codepages of sessions started by this process, and the default
721 codepage for drawing in PM; is inherited by kids. Does not affect the
722 out- and in-codepages of the session.]
726 returns the PID of the parent process.
728 =item C<ppidOf($pid = $$)>
730 returns the PID of the parent process of $pid. -1 on error.
732 =item C<sidOf($pid = $$)>
734 returns the session id of the process id $pid. -1 on error.
738 =head2 Control of VIO sessions
740 VIO applications are applications running in a text-mode session.
746 gets code page used for screen output (glyphs). -1 means that a user font
749 =item C<out_codepage_set($cp)>
751 sets code page used for screen output (glyphs). -1 switches to a preloaded
752 user font. -2 switches off the preloaded user font.
756 gets code page used for keyboard input. 0 means that a hardware codepage
759 =item C<in_codepage_set($cp)>
761 sets code page used for keyboard input.
763 =item C<($w, $h) = scrsize()>
765 width and height of the given console window in character cells.
767 =item C<scrsize_set([$w, ] $h)>
769 set height (and optionally width) of the given console window in
770 character cells. Use 0 size to keep the old size.
772 =item C<($s, $e, $w, $a) = cursor()>
774 gets start/end lines of the blinking cursor in the charcell, its width
775 (1 on text modes) and attribute (-1 for hidden, in text modes other
776 values mean visible, in graphic modes color).
778 =item C<cursor_set($s, $e, [$w [, $a]])>
780 sets start/end lines of the blinking cursor in the charcell. Negative
781 values mean percents of the character cell height.
785 gets a buffer with characters and attributes of the screen.
787 =item C<screen_set($buffer)>
789 restores the screen given the result of screen(). E.g., if the file
790 C<$file> contains the screen contents, then
792 open IN, $file or die;
796 $in .= qq(\0) x (length($s) - length $in);
797 substr($in, length $s) = '';
800 will restore the screen content even if the height of the window
801 changed (if the width changed, more manipulation is needed).
805 =head2 Control of the process list
807 With the exception of Title_set(), all these calls require that PM is
808 running, they would not work under alternative Session Managers.
812 =item process_entry()
814 returns a list of the following data:
820 Title of the process (in the C<Ctrl-Esc> list);
824 window handle of switch entry of the process (in the C<Ctrl-Esc> list);
828 window handle of the icon of the process;
832 process handle of the owner of the entry in C<Ctrl-Esc> list;
836 process id of the owner of the entry in C<Ctrl-Esc> list;
840 session id of the owner of the entry in C<Ctrl-Esc> list;
844 whether visible in C<Ctrl-Esc> list;
848 whether item cannot be switched to (note that it is not actually
849 grayed in the C<Ctrl-Esc> list));
853 whether participates in jump sequence;
857 program type. Possible values are:
866 Although there are several other program types for WIN-OS/2 programs,
867 these do not show up in this field. Instead, the PROG_VDM or
868 PROG_WINDOWEDVDM program types are used. For instance, for
869 PROG_31_STDSEAMLESSVDM, PROG_WINDOWEDVDM is used. This is because all
870 the WIN-OS/2 programs run in DOS sessions. For example, if a program
871 is a windowed WIN-OS/2 program, it runs in a PROG_WINDOWEDVDM
872 session. Likewise, if it's a full-screen WIN-OS/2 program, it runs in
881 Optional arguments: the pid and the window-handle of the application running
882 in the OS/2 session to query.
884 =item process_hentry()
886 similar to process_entry(), but returns a hash reference, the keys being
888 title owner_hwnd icon_hwnd owner_phandle owner_pid owner_sid
889 visible nonswitchable jumpable ptype sw_entry
891 (a copy of the list of keys is in @hentry_fields).
893 =item process_entries()
895 similar to process_entry(), but returns a list of array reference for all
896 the elements in the switch list (one controlling C<Ctrl-Esc> window).
898 =item process_hentries()
900 similar to process_hentry(), but returns a list of hash reference for all
901 the elements in the switch list (one controlling C<Ctrl-Esc> window).
905 changes a process entry, arguments are the same as process_entry() returns.
907 =item change_entryh()
909 Similar to change_entry(), but takes a hash reference as an argument.
913 returns the C<owner_hwnd> of the process entry (for VIO windowed processes
914 this is the frame window of the session).
918 returns the text of the task switch menu entry of the current session.
919 (There is no way to get this info in non-standard Session Managers. This
920 implementation is a shortcut via process_entry().)
922 =item C<Title_set(newtitle)>
924 tries two different interfaces. The Session Manager one does not work
925 with some windows (if the title is set from the start).
926 This is a limitation of OS/2, in such a case $^E is set to 372 (type
930 for a funny - and wrong - explanation ;-). In such cases a
931 direct-manipulation of low-level entries is used (same as bothTitle_set()).
932 Keep in mind that some versions of OS/2 leak memory with such a manipulation.
936 returns text of the titlebar of the current process' window.
938 =item C<winTitle_set(newtitle)>
940 sets text of the titlebar of the current process' window. The change does not
941 affect the text of the switch entry of the current window.
943 =item C<swTitle_set(newtitle)>
945 sets text of the task switch menu entry of the current process' window. [There
946 is no API to query this title.] Does it via SwitchEntry interface,
947 not Session manager interface. The change does not affect the text of the
948 titlebar of the current window.
950 =item C<bothTitle_set(newtitle)>
952 sets text of the titlebar and task switch menu of the current process' window
953 via direct manipulation of the windows' texts.
955 =item C<SwitchToProgram([$sw_entry])>
957 switch to session given by a switch list handle (defaults to the entry of our process).
959 Use of this function causes another window (and its related windows)
960 of a PM session to appear on the front of the screen, or a switch to
961 another session in the case of a non-PM program. In either case,
962 the keyboard (and mouse for the non-PM case) input is directed to
967 =head2 Control of the PM windows
969 Some of these API's require sending a message to the specified window.
970 In such a case the process needs to be a PM process, or to be morphed
971 to a PM process via OS2::MorphPM().
973 For a temporary morphing to PM use L<OS2::localMorphPM class>.
975 Keep in mind that PM windows are engaged in 2 "orthogonal" window
976 trees, as well as in the z-order list.
978 One tree is given by the I<parent/child> relationship. This
979 relationship affects drawing (child is drawn relative to its parent
980 (lower-left corner), and the drawing is clipped by the parent's
981 boundary; parent may request that I<it's> drawing is clipped to be
982 confined to the outsize of the childs and/or siblings' windows);
983 hiding; minimizing/restoring; and destroying windows.
985 Another tree (not necessarily connected?) is given by I<ownership>
986 relationship. Ownership relationship assumes cooperation of the
987 engaged windows via passing messages on "important events"; e.g.,
988 scrollbars send information messages when the "bar" is moved, menus
989 send messages when an item is selected; frames
990 move/hide/unhide/minimize/restore/change-z-order-of owned frames when
991 the owner is moved/etc., and destroy the owned frames (even when these
992 frames are not descendants) when the owner is destroyed; etc. [An
993 important restriction on ownership is that owner should be created by
994 the same thread as the owned thread, so they engage in the same
997 Windows may be in many different state: Focused (take keyboard events) or not,
998 Activated (=Frame windows in the I<parent/child> tree between the root and
999 the window with the focus; usually indicate such "active state" by titlebar
1000 highlights, and take mouse events) or not, Enabled/Disabled (this influences
1001 the ability to update the graphic, and may change appearance, as for
1002 enabled/disabled buttons), Visible/Hidden, Minimized/Maximized/Restored, Modal
1005 The APIs below all die() on error with the message being $^E.
1009 =item C<WindowText($hwnd)>
1011 gets "a text content" of a window. Requires (morphing to) PM.
1013 =item C<WindowText_set($hwnd, $text)>
1015 sets "a text content" of a window. Requires (morphing to) PM.
1017 =item C<($x, $y, $flags, $width, $height, $behind, @rest) = WindowPos($hwnd)>
1019 gets window position info as 8 integers (of C<SWP>), in the order suitable
1020 for WindowPos_set(). @rest is marked as "reserved" in PM docs. $flags
1021 is a combination of C<SWP_*> constants.
1023 =item C<$hash = hWindowPos($hwnd)>
1025 gets window position info as a hash reference; the keys are C<flags width
1026 height x y behind hwnd reserved1 reserved2>.
1030 exit unless $hash->{flags} & SWP_MAXIMIZE; # Maximized
1032 =item C<WindowPos_set($hwnd, $x, $y, $flags = SWP_MOVE, $width = 0, $height = 0, $behind = HWND_TOP)>
1034 Set state of the window: position, size, zorder, show/hide, activation,
1035 minimize/maximize/restore etc. Which of these operations to perform
1036 is governed by $flags.
1038 =item C<hWindowPos_set($hash, [$hwnd])>
1040 Same as C<WindowPos_set>, but takes the position from keys C<fl width height
1041 x y behind hwnd> of the hash referenced by $hash. If $hwnd is explicitly
1042 specified, it overrides C<$hash->{hwnd}>. If $hash->{flags} is not specified,
1043 it is calculated basing on the existing keys of $hash. Requires (morphing to) PM.
1047 hWindowPos_set {flags => SWP_MAXIMIZE}, $hwnd; # Maximize
1049 =item C<($pid, $tid) = WindowProcess($hwnd)>
1051 gets I<PID> and I<TID> of the process associated to the window.
1053 =item C<ClassName($hwnd)>
1055 returns the class name of the window.
1057 If this window is of any of the preregistered WC_* classes the class
1058 name returned is in the form "#nnnnn", where "nnnnn" is a group
1059 of up to five digits that corresponds to the value of the WC_* class name
1064 returns the handle of the focus window. Optional argument for specifying
1067 =item C<FocusWindow_set($hwnd)>
1069 set the focus window by handle. Optional argument for specifying the desktop
1070 to use. E.g, the first entry in program_entries() is the C<Ctrl-Esc> list.
1071 To show an application, use either one of
1073 WinShowWindow( $hwnd, 1 );
1074 FocusWindow_set( $hwnd );
1075 SwitchToProgram($switch_handle);
1077 (Which work with alternative focus-to-front policies?) Requires
1080 Switching focus to currently-unfocused window moves the window to the
1081 front in Z-order; use FocusWindow_set_keep_Zorder() to avoid this.
1083 =item C<FocusWindow_set_keep_Zorder($hwnd)>
1085 same as FocusWindow_set(), but preserves the Z-order of windows.
1087 =item C<ActiveWindow([$parentHwnd])>
1089 gets the active subwindow's handle for $parentHwnd or desktop.
1090 Returns FALSE if none.
1092 =item C<ActiveWindow_set($hwnd, [$parentHwnd])>
1094 sets the active subwindow's handle for $parentHwnd or desktop. Requires (morphing to) PM.
1096 =item C<ShowWindow($hwnd [, $show])>
1098 Set visible/hidden flag of the window. Default: $show is TRUE.
1100 =item C<EnableWindowUpdate($hwnd [, $update])>
1102 Set window visibility state flag for the window for subsequent drawing.
1103 No actual drawing is done at this moment. Use C<ShowWindow($hwnd, $state)>
1104 when redrawing is needed. While update is disabled, changes to the "window
1105 state" do not change the appearance of the window. Default: $update is TRUE.
1107 (What is manipulated is the bit C<WS_VISIBLE> of the window style.)
1109 =item C<EnableWindow($hwnd [, $enable])>
1111 Set the window enabled state. Default: $enable is TRUE.
1113 Results in C<WM_ENABLED> message sent to the window. Typically, this
1114 would change the appearence of the window. If at the moment of disabling
1115 focus is in the window (or a descendant), focus is lost (no focus anywhere).
1116 If focus is needed, it can be reassigned explicitly later.
1118 =item IsWindowEnabled(), IsWindowVisible(), IsWindowShowing()
1120 these functions take $hwnd as an argument. IsWindowEnabled() queries
1121 the state changed by EnableWindow(), IsWindowVisible() the state changed
1122 by ShowWindow(), IsWindowShowing() is true if there is a part of the window
1123 visible on the screen.
1125 =item C<PostMsg($hwnd, $msg, $mp1, $mp2)>
1127 post message to a window. The meaning of $mp1, $mp2 is specific for each
1128 message id $msg, they default to 0. E.g.,
1130 use OS2::Process qw(:DEFAULT WM_SYSCOMMAND WM_CONTEXTMENU
1131 WM_SAVEAPPLICATION WM_QUIT WM_CLOSE
1132 SC_MAXIMIZE SC_RESTORE);
1133 $hwnd = process_hentry()->{owner_hwnd};
1134 # Emulate choosing `Restore' from the window menu:
1135 PostMsg $hwnd, WM_SYSCOMMAND, MPFROMSHORT(SC_RESTORE); # Not immediate
1137 # Emulate `Show-Contextmenu' (Double-Click-2), two ways:
1138 PostMsg ActiveWindow, WM_CONTEXTMENU;
1139 PostMsg FocusWindow, WM_CONTEXTMENU;
1141 /* Emulate `Close' */
1142 PostMsg ActiveWindow, WM_CLOSE;
1144 /* Same but with some "warnings" to the application */
1145 $hwnd = ActiveWindow;
1146 PostMsg $hwnd, WM_SAVEAPPLICATION;
1147 PostMsg $hwnd, WM_CLOSE;
1148 PostMsg $hwnd, WM_QUIT;
1150 In fact, MPFROMSHORT() may be omitted above.
1152 For messages to other processes, messages which take/return a pointer are
1157 The functions MPFROMSHORT(), MPVOID(), MPFROMCHAR(), MPFROM2SHORT(),
1158 MPFROMSH2CH(), MPFROMLONG() can be used the same way as from C. Use them
1159 to construct parameters $m1, $m2 to PostMsg().
1161 These functions are not exported by default.
1163 =item C<$eh = BeginEnumWindows($hwnd)>
1165 starts enumerating immediate child windows of $hwnd in z-order. The
1166 enumeration reflects the state at the moment of BeginEnumWindows() calls;
1167 use IsWindow() to be sure. All the functions in this group require (morphing to) PM.
1169 =item C<$kid_hwnd = GetNextWindow($eh)>
1171 gets the next kid in the list. Gets 0 on error or when the list ends.
1173 =item C<EndEnumWindows($eh)>
1175 End enumeration and release the list.
1177 =item C<@list = ChildWindows([$hwnd])>
1179 returns the list of child windows at the moment of the call. Same remark
1180 as for enumeration interface applies. Defaults to HWND_DESKTOP.
1185 printf ' ' x $o . "%#x\n", $h;
1186 l($o+2,$_) for ChildWindows $h;
1190 =item C<IsWindow($hwnd)>
1192 true if the window handle is still valid.
1194 =item C<QueryWindow($hwnd, $type)>
1196 gets the handle of a related window. $type should be one of C<QW_*> constants.
1198 =item C<IsChild($hwnd, $parent)>
1200 return TRUE if $hwnd is a descendant of $parent.
1202 =item C<WindowFromId($hwnd, $id)>
1204 return a window handle of a child of $hwnd with the given $id.
1206 hwndSysMenu = WinWindowFromID(hwndDlg, FID_SYSMENU);
1207 WinSendMsg(hwndSysMenu, MM_SETITEMATTR,
1208 MPFROM2SHORT(SC_CLOSE, TRUE),
1209 MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED));
1211 =item C<WindowFromPoint($x, $y [, $hwndParent [, $descedantsToo]])>
1213 gets a handle of a child of $hwndParent at C<($x,$y)>. If $descedantsToo
1214 (defaulting to 1) then children of children may be returned too. May return
1215 $hwndParent (defaults to desktop) if no suitable children are found,
1216 or 0 if the point is outside the parent.
1218 $x and $y are relative to $hwndParent.
1220 =item C<EnumDlgItem($dlgHwnd, $type [, $relativeHwnd])>
1222 gets a dialog item window handle for an item of type $type of $dlgHwnd
1223 relative to $relativeHwnd, which is descendant of $dlgHwnd.
1224 $relativeHwnd may be specified if $type is EDI_FIRSTTABITEM or
1227 The return is always an immediate child of hwndDlg, even if hwnd is
1228 not an immediate child window. $type may be
1232 =item EDI_FIRSTGROUPITEM
1234 First item in the same group.
1236 =item EDI_FIRSTTABITEM
1238 First item in dialog with style WS_TABSTOP. hwnd is ignored.
1240 =item EDI_LASTGROUPITEM
1242 Last item in the same group.
1244 =item EDI_LASTTABITEM
1246 Last item in dialog with style WS_TABSTOP. hwnd is ignored.
1248 =item EDI_NEXTGROUPITEM
1250 Next item in the same group. Wraps around to beginning of group when
1251 the end of the group is reached.
1253 =item EDI_NEXTTABITEM
1255 Next item with style WS_TABSTOP. Wraps around to beginning of dialog
1256 item list when end is reached.
1258 =item EDI_PREVGROUPITEM
1260 Previous item in the same group. Wraps around to end of group when the
1261 start of the group is reached. For information on the WS_GROUP style,
1264 =item EDI_PREVTABITEM
1266 Previous item with style WS_TABSTOP. Wraps around to end of dialog
1267 item list when beginning is reached.
1271 =item DesktopWindow()
1273 gets the actual window handle of the PM desktop; most APIs accept the
1274 pseudo-handle C<HWND_DESKTOP> instead. Keep in mind that the WPS
1275 desktop (one with WindowText() being C<"Desktop">) is a different beast?!
1277 =item TopLevel($hwnd)
1279 gets the toplevel window of $hwnd.
1281 =item ResetWinError()
1283 Resets $^E. One may need to call it before the C<Win*>-class APIs which may
1284 return 0 during normal operation. In such a case one should check both
1285 for return value being zero and $^E being non-zero. The following APIs
1286 do ResetWinError() themselves, thus do not need an explicit one:
1295 This function is normally not needed. Not exported by default.
1299 =head2 Control of the PM data
1303 =item ActiveDesktopPathname()
1305 gets the path of the directory which corresponds to Desktop.
1309 gets the content of the clipboard. An optional argument is the format
1310 of the data in the clipboard (defaults to C<CF_TEXT>).
1312 Note that the usual convention is to have clipboard data with
1313 C<"\r\n"> as line separators.
1315 =item ClipbrdText_set($txt)
1317 sets the text content of the clipboard. Unless the optional argument
1318 is TRUE, will convert newlines to C<"\r\n">. Another optional
1319 argument is the format of the data in the clipboard (defaults to
1322 =item InvalidateRect
1324 =item CreateFrameControl
1326 =item ClipbrdFmtInfo
1338 =item ClipbrdData_set
1340 =item ClipbrdOwner_set
1342 =item ClipbrdViewer_set
1344 =item EnumClipbrdFmts
1360 =item SystemAtomTable
1362 =item CreateAtomTable
1364 =item DestroyAtomTable
1366 Low-level methods to access clipboard and the atom table(s).
1370 =head1 OS2::localMorphPM class
1372 This class morphs the process to PM for the duration of the given scope.
1375 my $h = OS2::localMorphPM->new(0);
1379 The argument has the same meaning as one to OS2::MorphPM(). Calls can
1380 nest with internal ones being NOPs.
1411 Document and test: Query/SetWindowULong/Short/Ptr, SetWindowBits.
1412 InvalidateRect, CreateFrameControl, ClipbrdFmtInfo ClipbrdOwner
1413 ClipbrdViewer ClipbrdData OpenClipbrd CloseClipbrd ClipbrdData_set
1414 ClipbrdOwner_set ClipbrdViewer_set EnumClipbrdFmts EmptyClipbrd
1415 AddAtom FindAtom DeleteAtom AtomUsage AtomName AtomLength
1416 SystemAtomTable CreateAtomTable DestroyAtomTable
1418 Implement SOMETHINGFROMMR.
1421 >But I wish to change the default button if the user enters some
1422 >text into an entryfield. I can detect the entry ok, but can't
1423 >seem to get the button to change to default.
1425 >No matter what message I send it, it's being ignored.
1427 You need to get the style of the buttons using WinQueryWindowULong/QWL_STYLE,
1428 set and reset the BS_DEFAULT bits as appropriate and then use
1429 WinSetWindowULong/QWL_STYLE to set the button style.
1430 Something like this:
1431 hwnd1 = WinWindowFromID (hwnd, id1);
1432 hwnd2 = WinWindowFromID (hwnd, id2);
1433 style1 = WinQueryWindowULong (hwnd1, QWL_STYLE);
1434 style2 = WinQueryWindowULong (hwnd2, QWL_STYLE);
1435 style1 |= style2 & BS_DEFAULT;
1436 style2 &= ~BS_DEFAULT;
1437 WinSetWindowULong (hwnd1, QWL_STYLE, style1);
1438 WinSetWindowULong (hwnd2, QWL_STYLE, style2);
1440 > How to do query and change a frame creation flags for existing window?
1442 Set the style bits that correspond to the FCF_* flag for the frame
1443 window and then send a WM_UPDATEFRAME message with the appropriate FCF_*
1447 ulFrameStyle = WinQueryWindowULong( WinQueryWindow(hwnd, QW_PARENT),
1449 ulFrameStyle = (ulFrameStyle & ~FS_SIZEBORDER) | FS_BORDER;
1450 WinSetWindowULong( WinQueryWindow(hwnd, QW_PARENT),
1453 WinSendMsg( WinQueryWindow(hwnd, QW_PARENT),
1455 MPFROMP(FCF_SIZEBORDER),
1458 If the FCF_* flags you want to change does not have a corresponding FS_*
1459 style (i.e. the FCF_* flag corresponds to the presence/lack of a frame
1460 control rather than a property of the frame itself) then you create or
1461 destroy the appropriate control window using the correct FID_* window
1462 identifier and then send the WM_UPDATEFRAME message with the appropriate
1465 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*
1466 | SetFrameBorder() |
1467 | Changes a frame window's border to the requested type. |
1469 | Parameters on entry: |
1470 | hwndFrame -> Frame window whose border is to be changed. |
1471 | ulBorderStyle -> Type of border to change to. |
1474 | BOOL -> Success indicator. |
1476 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
1477 BOOL SetFrameBorder( HWND hwndFrame, ULONG ulBorderType ) {
1479 BOOL fSuccess = TRUE;
1481 ulFrameStyle = WinQueryWindowULong( hwndFrame, QWL_STYLE );
1483 switch ( ulBorderType ) {
1484 case FS_SIZEBORDER :
1485 ulFrameStyle = (ulFrameStyle & ~(FS_DLGBORDER | FS_BORDER))
1490 ulFrameStyle = (ulFrameStyle & ~(FS_SIZEBORDER | FS_BORDER))
1495 ulFrameStyle = (ulFrameStyle & ~(FS_SIZEBORDER | FS_DLGBORDER))
1505 fSuccess = WinSetWindowULong( hwndFrame, QWL_STYLE, ulFrameStyle );
1508 fSuccess = (BOOL)WinSendMsg( hwndFrame, WM_UPDATEFRAME, 0, 0 );
1510 fSuccess = WinInvalidateRect( hwndFrame, NULL, TRUE );
1514 return ( fSuccess );
1516 } // End SetFrameBorder()
1518 hwndMenu=WinLoadMenu(hwndParent,NULL,WND_IMAGE);
1519 WinSetWindowUShort(hwndMenu,QWS_ID,FID_MENU);
1520 ulStyle=WinQueryWindowULong(hwndMenu,QWL_STYLE);
1521 WinSetWindowULong(hwndMenu,QWL_STYLE,ulStyle|MS_ACTIONBAR);
1522 WinSendMsg(hwndParent,WM_UPDATEFRAME,MPFROMSHORT(FCF_MENU),0L);
1524 OS/2-windows have another "parent" called the *owner*,
1525 which must be set separately - to get a close relationship:
1527 WinSetOwner (hwndFrameChild, hwndFrameMain);
1529 Now your child should move with your main window!
1530 And always stays on top of it....
1532 To avoid this, for example for dialogwindows, you can
1533 also "disconnect" this relationship with:
1535 WinSetWindowBits (hwndFrameChild, QWL_STYLE
1536 , FS_NOMOVEWITHOWNER
1537 , FS_NOMOVEWITHOWNER);
1539 Adding a button icon later:
1541 /* switch the button style to BS_MINIICON */
1542 WinSetWindowBits(hwndBtn, QWL_STYLE, BS_MINIICON, BS_MINIICON) ;
1544 /* set up button control data */
1546 bcd.cb = sizeof(BTNCDATA);
1547 bcd.hImage = WinLoadPointer(HWND_DESKTOP, dllHandle, ID_ICON_BUTTON1) ;
1548 bcd.fsCheckState = bcd.fsHiliteState = 0 ;
1552 wp.fsStatus = WPM_CTLDATA;
1555 /* add the icon on the button */
1556 WinSendMsg(hwndBtn, WM_SETWINDOWPARAMS, (MPARAM)&wp, NULL);
1558 MO> Can anyone tell what OS/2 expects of an application to be properly
1559 MO> minimized to the desktop?
1560 case WM MINMAXFRAME :
1562 BOOL fShow = ! (((PSWP) mp1)->fl & SWP MINIMIZE);
1567 WinEnableWindowUpdate ( hwnd, FALSE );
1569 for (henum=WinBeginEnumWindows(hwnd);
1570 (hwndChild = WinGetNextWindow (henum)) != 0; )
1571 WinShowWindow ( hwndChild, fShow );
1573 WinEndEnumWindows ( henum );
1574 WinEnableWindowUpdate ( hwnd, TRUE );
1578 Why C<hWindowPos DesktopWindow> gives C<< behind => HWND_TOP >>?
1582 the majority of the APIs of this module set $^E on failure (no matter
1583 whether they die() on failure or not). By the semantic of PM API
1584 which returns something other than a boolean, it is impossible to
1585 distinguish failure from a "normal" 0-return. In such cases C<$^E ==
1586 0> indicates an absence of error.
1590 In addition to symbols described above, the following constants (available
1591 also via module C<OS2::Process::Const>) are exportable. Note that these
1592 symbols live in package C<OS2::Process::Const>, they are not available
1593 by full name through C<OS2::Process>!
1595 HWND_* Standard (abstract) window handles
1597 SC_* WM_SYSCOMMAND flavor
1598 SWP_* Size/move etc flag
1599 WC_* Standard window classes
1600 PROG_* Program category (PM, VIO etc)
1601 QW_* Query-Window flag
1602 EDI_* Enumerate-Dialog-Item code
1603 WS_* Window Style flag
1604 QWS_* Query-window-UShort offsets
1605 QWP_* Query-window-pointer offsets
1606 QWL_* Query-window-ULong offsets
1607 FF_* Frame-window state flags
1608 FI_* Frame-window information flags
1609 LS_* List box styles
1611 FCF_* Frame creation flags
1614 TBM_* Title bar messages?
1615 CF_* Clipboard formats
1616 CFI_* Clipboard storage type
1617 FID_* ids of subwindows of frames
1621 whether a given API dies or returns FALSE/empty-list on error may be
1622 confusing. This may change in the future.
1626 Andreas Kaiser <ak@ananke.s.bawue.de>,
1627 Ilya Zakharevich <ilya@math.ohio-state.edu>.
1631 C<spawn*>() system calls, L<OS2::Proc> and L<OS2::WinObject> modules.