Implement the basic SWT class hierarchy: from o.e.swt.widgets.Widget
to o.e.swt.widgets.Shell
to be able to create windows in the
context of SWT. This will allow to do many other things just as they
should be done. The test example should create and show two SWT windows:
the top shell (filled with the default SWT background color, without any
content) and the secondary shell (also empty) which is always above the
top shell. Also it should handle the event queue in minimal, i.e. react to
the close action, clean up correctly and exit.
In fact, that there are two different layers of output device
abstraction in OS/2: device contexts and presentation spaces, as opposed
to Windows where the device context plays the role of both -- and handle
to it is just allocated and returned by Drawable.internal_new_GC()
method which is overriden for different types of devices. In OS/2 we use
the presentation space handle as a return value of the internal_new_GC()
.
The handle to the device context is stored in the GCData.hdc
field if non-null GCData object is passed to the internal_new_GC()
.
For windows, the device context is not really opened by the
internal_new_GC()
, the handle to it is just obtained via
OS.GpiQueryDevice()
call with the presentation space handle
of the window passed as an argument. Correspondingly, it is not closed by
the internal_dispose_GC()
.
For other devices, that require the real creation of the device context
(which, together with the creation of the presentation space and
associating the latter with the former, is made inside the internal_new_GC()
),
the GCData object passed in should not be null
, because the
handle of the device context will be necessary to correctly close this
context by the internal_dispose_GC()
.
Below is the approximate correspondence between Windows device context functions and OS/2 ones:
Windows GUI API | OS/2 PM API | Remarks |
hDC = BeginPaint(hwnd...) | hps = WinBeginPaint(hwnd, NULL...) [Cached PS] | To draw during WM_PAINT message |
EndPaint(hwnd...) | WinEndPaint(hps) | |
hDC = GetDC(hwnd) or hDC = GetWindowDC(hwnd) | hps = WinGetPS(hwnd), hps = WinGetScreenPS(hwndDesktop) [Cached PS] | To draw during any message |
ReleaseDC(hwnd, hDC) | WinReleasePS(hps) | |
hDC = CreateDC(...) | hdc = WinOpenWindowDC(hwnd) or DevOpenDC(...), hps = GpiCreatePS(hab, hdc...) [Micro/Normal PS] | To dtaw on any device (usually display or printer) |
DeleteDC(hDC) | GpiDestroyPS(hps), DevCloseDC(hdc) | |
CreateCompatibleDC(hDC) | hdcCompat = DevOpenDC(...hDC) | DC compatible with given |
The coordinate space in OS/2 is flipped horizontally when compared to
its traditional orientation in the context of windows. That is, the origin
of the coordinate space is located in the lower left corner but not in the
upper left, as it considered to be in SWT or in Windows, in particular.
This should be always kept in mind. The formula to recalculate the
y coordinate of the rectangle from one system to another is
very simple: y = parentHeight - (y + height)
, where
parentHeight
is the height of the parent's space,
coordinates of the rectangle are relative to.
[Note: the following information is partially outdated, see
here] The package method
Control.getHeight()
can be used by classes within the
o.e.swt.widgets
package to easily obtain the height of the
control itself and/or the height of its parent using parent.getHeight()
call (note, that if the parent is null
or when the control is
a Shell
instance, the Display.getHeight()
must
be used to obtain the parent's height). Also, the Control.getBounds(SWP)
package method returns the height of the control's parent
(respecting the situation when the parent is null
or the
control is a Shell
) as the side effect of its invocation,
which is used, for example by the setBounds()
method. But for
simple calculations the getHeight()
method is more preferable
since it does less calculations.
The above applies to all Win*
API calls relative to
sizing/positioning (such as WinQueryWindowRect()
,
WinSetWindowPos()
and so on). Hopefully, for Gpi*
calls we can setup the automatic horizontal flipping of the coordinate
space to be done by changing the default view transformation matrix of the
window's presentation space, so there's no need to do any
coordinate conversion when using Gpi*
functions (see also
task notes in the SWT Step 003).
In OS/2 every window has two types of relationship: parent-child and ownership. In both SWT and Windows there is only the parentship. Although the code for OS/2 related to these things will be a bit more complicated, the situation is very simple: in most cases (window controls) the parent and the owner is be the same. For shells the parent is the Desktop and the owner is null (for top shells) or another shell (for secondary ones). Also for some other windows (such as popup menus) the Desktop willbe the parent. In SWT the term (and the field) parent references to the real parent (the window which confines a child visually) except (not embedded) shells, for which the parent is their owner (the window which receives messages from them).
In OS/2 the frame window is the composite window of the special class
containing the decorative elements such as a titlebar, min/max buttons,
scroll bars (which are all windows themselves) as its children and ownees,
as opposed to Windows where this decoration is defined just by window
style flags in a call to the window creation function. So, the work with
frame windows (starting with the Decorations class in the widget
hierarchy) in OS/2 is slightly different -- in particular, the
Decorations.createHandle()
(see below) does some additional
calls to create various frame controls (decorative elements) for the frame
window being created.
Dialog windows in OS/2 are just extensions of frame windows, they
subclass them and do some additional work (for example, handle the focus
traversal over dialog controls and maintain the result code of the dialog
window). Possibly, in SWT these windows will not be used at all and their
behavior will be just emulated on the basis of the ordinary Shell
widget.
The common point of the native window creation is the Control.createHandle()
method, which is used almost by all subclasses. The logic of its work is
as follows:
Control
's parent is not null
the hwndOwner
of the window being created is the
parent.handle
, otherwise null
.Control
supplies some nonzero handle value
before making a call to its createHandle()
method (i.e. in
the constructor, before calling the createWidget()
) it is
used as the window's hwndParent
. Otherwise the
parent.handle
is used as the hwndParent
or
HWND_DESKTOP
if the parent is null
.windowClass()
and widgetStyle()
methods,
respectively. These methods are usually overrided by subclasses.Display.windowProc()
becomes the new window procedure, which calls the Control.windowProc()
,
which usually calls the old window procedure via the Control.callWindowProc()
.Operation | Status | Remarks |
---|---|---|
Partially implement the Widget class |
Done [dmik] | Only the character translation is not implemented. |
Partially Implement the GC class |
Delayed | Almost completely commented. The major work will be done on the step 3. |
Add EventTable , Listener , Event ,
TypedListener to compilation |
Done [dmik] | |
Implement Display.internal_new_GC() and Display.internal_dispose_GC() |
Done [dmik] | See Task notes above. |
Add o.e.swt.events.*Listener , *Event and
*Adapter classes to compilation |
Done [dmik] | |
Add o.e.swt.accessibility.* (common and emulated) to
compilation |
Done [dmik] | |
Add message time obtaining to Widget.sendEvent() and
Widget.postEvent() |
Done [dmik] | |
Implement OS.WinSendMsg , OS.WinPostMsg() ,
OS.WinQueryMsgTime() |
Done [dmik] | |
Add standard WM_* constants |
Done [dmik] | Most of them are commented and will be uncommented on demand |
Add standard WC_* constants |
Done [dmik] | Most of them are commented and will be uncommented on demand. Since they actually are integer values (integer atoms) but natives that use them require PSZ as a class name, a special static method getAtom() is added to PSZ class that returns a string representation of an atom. |
Implement the WidgetTable class, OS.Win[Set|Query]Window[ULong|UShort]()
and add QW[L|S]_* constants |
Done [dmik] | |
Implement the OS.WinQueryClassInfo() and add
CLASSINFO class |
Done [dmik] | |
Implement OS.WinQueryWindowRect() , OS.WinMapWindowPoints() ,
RECTL class |
Done [dmik] | |
Implement OS.WinIsWindowEnabled() , WinIsWindowVisible() ,
WinQueryFocus() , WinQueryWindow() ,
WinShowWindow() |
Done [dmik] | |
Implement OS.WinGetPS() , WinReleasePS() ,
WinBeginPaint() , WinEndPaint() ,
WinInvalidateRect() , WinUpdateWindow() |
Done [dmik] | |
Implement the OS.WinQuerySysValue() and SV_*
constants |
Done [dmik] | |
Add the static Display.height field |
Done [dmik] | This field is used to flip the window coordinate space vertically |
Add o.e.swt.internal.pm.MRESULT class |
Done [dmik] | The reason it was added is that, as opposed to the simple int
type, null can be returned by individual message handlers
indicating that the message hasn't been processed and therefore
should be passed to the default window procedure. |
Implement the helper function OS.WinCallWindowProc() |
Done [dmik] | To get the ability to call the window procedure given as the int value (actually the C pointer to a function) |
implement the OS.WinSetWindowPos() and SWP_*
constants |
Done [dmik] | |
implement the OS.WinCreateFrameControls() and
FCF_* , FS_* , FF_* constants |
Done [dmik] | |
Implement the OS.WinGetScreenPC() and OS.GpiQueryDevice() |
Done [dmik] | |
Implement OS.WinQueryWindowTextLength() ,
WinQueryWindowText() , WinSetWindowText() ,
add a new constructor to the PSZ class taking an integer
as the length of an empty string to create |
Done [dmik] | Used to get/set shell titles |
Implement the OS.WinFillRect() and OS.objcpy()
for the RECTL structure |
Done [dmik] | Needed to handle WM_ERASEBACKGROUND message. |
Partially implement the following classes to reach the step
objective: o.e.swt.widgets.Control , Scrollable ,
Composite , Canvas , Decorations ,
Shell and some others (WidgetTable etc) they
depend on |
Done [dmik] | The majority of work has been done in the Control, Decorations and Shell classes, others are almost fully commented. |
Add the SWT002 testcase |
Done [dmik] | Note: WinDestroyWindow() is not called for secondary
shells explicitly. It's a planned behavior of SWT (see the
description of the Widget.destroyWidget() ). It is
suitable for OS/2 when the window's owner is a WC_FRAME
window. See remarks inside the Control.createHandle() . |