summaryrefslogtreecommitdiff
path: root/libjava/jni
diff options
context:
space:
mode:
authorgraydon <graydon@138bc75d-0d04-0410-961f-82ee72b054a4>2004-09-02 05:10:34 +0000
committergraydon <graydon@138bc75d-0d04-0410-961f-82ee72b054a4>2004-09-02 05:10:34 +0000
commit998d01227e4b1c1980db971f01db98195a7d4eaa (patch)
treea420c1005dbef38d790847b62b0d57eb9bc758cb /libjava/jni
parent9bc2282c56748dd872dfc03f953c8539f7cbab81 (diff)
downloadgcc-998d01227e4b1c1980db971f01db98195a7d4eaa.tar.gz
2004-08-31 Michael Koch <konqueror@gmx.de>
* javax/swing/plaf/basic/BasicTextAreaUI.java (create): New method. * javax/swing/text/DefaultHighlighter.java (DefaultHighlightPainter.debugRect): Removed. * javax/swing/text/StyleContext.java (DEFAULT_STYLE): New field. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicLookAndFeel.java (initComponentDefaults): Add keybindings for selection.backward and selection-forward for text components. * javax/swing/plaf/basic/BasicTextUI.java (paintSafely): Paint highlight only when something is actually selected. * javax/swing/text/DefaultCaret.java (handleHighlight): New method. (setSelectionVisible): Don't do anything when nothing changes. Handle highlight. (moveDot): Reimplemented. Handle highlight. (setDot): Set mark too. Handle highlight. (getSelectionPainter): New method. * javax/swing/text/DefaultEditorKit.java (defaultActions): Added new actions for text selection. * javax/swing/text/DefaultHighlighter.java (DefaultHighlightPainter): New inner class. (DefaultPainter): New field. (paint): Implemented. * javax/swing/text/PlainView.java (paint): Don't draw background here again. * javax/swing/text/Utilities.java (getTabbedTextWidth): Use width of ' ' instead of 'm' for tabsize. (drawTabbedText): Likewise. 2004-08-31 Graydon Hoare <graydon@redhat.com> * javax/swing/JComponent.java (resetKeyboardActions): Add null checks. 2004-08-31 Graydon Hoare <graydon@redhat.com> * javax/swing/DefaultButtonModel.java: Skip group notification when no group is set. 2004-08-31 Graydon Hoare <graydon@redhat.com> * javax/swing/JColorChooser.java: Make a couple inner classes static, for jikes. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicTextUI.java (RottView.modelToView): New method. (UpdateHandler): Renamed from EventHandler. (updateHandler): Renamed from eventHandler. (modelToView): Implemented. * javax/swing/text/AbstractDocument.java (BranchElement.getElement): Return null for non-existing indeces. (BranchElement.getElementIndex): Return 0 in some corner cases. * javax/swing/text/FieldView.java (modelToView): New method. * javax/swing/text/PlainView.java (modelToView): Made public. 2004-08-31 Kim Ho <kho@redhat.com> * Makefile.am: New files. * Makefile.in: Regenerate. * gcj/Makefile.in: Regenerate. * include/Makefile.in: Regenerate. * java/awt/Color.java: Fix documentation. (RGBtoHSB): Use floats for conversions. * javax/swing/ButtonGroup.java: Run Jalopy. (setSelected): Reimplement. * javax/swing/DefaultButtonModel.java: Run Jalopy. (changeState): Let ButtonGroup know that the button is changing state. * javax/swing/JColorChooser.java: Implement. * javax/swing/JLabel.java: Run Jalopy. * javax/swing/JSpinner.java: Run Jalopy. (setValue): New method. * javax/swing/JTabbedPane.java: Run Jalopy. (removeTabAt): Call correct remove method. * javax/swing/SpinnerNumberModel.java: Run Jalopy. (getPreviousValue): Compare minimum value. * javax/swing/Timer.java: Run Jalopy. (run): Comment out println. * javax/swing/ToolTipManager.java: (mouseMoved): Get new tooltip text for location. * javax/swing/colorchooser/AbstractColorChooserPanel.java: Jalopy and Javadoc. * javax/swing/colorchooser/ColorChooserComponentFactory.java: Implement. * javax/swing/colorchooser/DefaultColorSelectionModel.java: Run Jalopy. (setSelectedColor): Fire ChangeEvent. * javax/swing/colorchooser/DefaultHSBChooserPanel.java: New file. Implement. * javax/swing/colorchooser/DefaultPreviewPanel.java: Ditto. * javax/swing/colorchooser/DefaultRGBChooserPanel.java: Ditto. * javax/swing/colorchooser/DefaultSwatchChooserPanel.java: Ditto. * javax/swing/plaf/basic/BasicArrowButton.java: (getArrow): Fix size of upward pointing button. * javax/swing/plaf/basic/BasicColorChooserUI.java: Implement. * javax/swing/plaf/basic/BasicSliderUI.java: (getWidthOfWidestLabel): Use preferred dimensions. (getHeightOfTallestLabel): Ditto. * javax/swing/plaf/basic/BasicSpinnerUI.java: Run Jalopy. (mousePressed): Disable changes to spinner if it is not enabled. * testsuite/Makefile.in: Regenerate. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicTableHeaderUI.java, javax/swing/plaf/basic/BasicTableUI.java: Added copyright notice. 2004-08-31 Olga Rodimina <rodimina@redhat.com> * Makefile.am: Added new files. * Makefile.in: Regenerate. * javax/swing/ComboBoxEditor.java: Added javadocs. * javax/swing/ComboBoxModel.java: Likewise. * javax/swing/DefaultComboBoxModel.java: Implemented. * javax/swing/DefaultListCellRenderer.java: Added javadocs and ran through jalopy to fix formatting style. (getListCellRendererComponent): Use appropriate border if renderer has focus and use noFocusBorder when it doesn't. * javax/swing/JComboBox.java: Implemented. * javax/swing/JList.java: (locationToIndex): New Method. Implemented. (indexToLocation): New Method. * javax/swing/JPopupMenu.java: (visible): New field. (isVisible): Changed to use new field above. (setVisible): Likewise. * javax/swing/MutableComboBoxModel.java: Added javadocs. * javax/swing/plaf/basic/BasicArrowButton.java: (shadow): Changed default color to Color.gray. * javax/swing/plaf/basic/BasicComboBoxUI.java: New File. UI delegate for JComboBox. * javax/swing/plaf/basic/BasicComboPopup.java: New File. Popup menu containing list of JComboBox's items. * javax/swing/plaf/basic/BasicComboBoxEditor.java: New File. * javax/swing/plaf/basic/BasicComboBoxRenderer.java: New File. * javax/swing/plaf/basic/BasicComboBoxUI.java: New File. * javax/swing/plaf/basic/BasicComboPopup.java: New File. * javax/swing/plaf/basic/BasicPopupMenuUI.java: (popupMenuWillBecomeVisible): Set selected path to the first element only if it is of type MenuElement. Also fix formatting style. * javax/swing/plaf/basic/ComboPopup.java: Added javadocs and missing methods signatures. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/text/AbstractDocument.java (createBranchElement): Use new constructor of BranchElement. (createLeafElement): Renamed arguments. (getRootElements): Implemented. (BranchElement.start): Removed. (BranchElement.end): Likewise. (BranchElement.BranchElement): Fixed arguments. (BranchElement.getEndOffset): Reimplemented. (BranchElement.getStartOffset): Likewis. * javax/swing/text/DefaultCaret.java (paint): Draw simple vertical line as caret instead of a rectangle. * javax/swing/text/JTextComponent.java (setText): Use doc directly. * javax/swing/text/PlainView.java (nextTabStop): Implemented. * javax/swing/text/Utilities.java (drawTabbedText): nextTabStop() returns an absolute x position. (getTabbedTextWidth): Likewise. 2004-08-31 Graydon Hoare <graydon@redhat.com> * java/awt/Component.java (isFocusTraversable): Predicate on isLightweight() (setFocusable): Set isFocusTraversableOverridden. (requestFocus): Predicate peer dispatch on !isLightweight() (requestFocusInWindow): Likewise. (dispatchEventImpl): Coordinate with KeyboardFocusManager. * java/awt/Container.java (dispatchEventImpl): Predicate on event mask. (LightweightDispatcher): Remove focus machinery. * java/awt/DefaultFocusTraversalPolicy.java (accept): Expand predicate to include isFocusable(). * java/awt/DefaultKeyboardFocusManager.java: Globally change c.dispatchEvent(e) to redispatchEvent(c,e) * java/awt/KeyboardFocusManager.java (redispatchEvent): Synchronize on event to prevent feedback. * javax/swing/AbstractButton.java (ButtonFocusListener): Remove class. (init): Set focusPainted, focusable. * javax/swing/ActionMap.java (get): Check parent for null. * javax/swing/InputMap.java (get): Likewise. * javax/swing/JComponent.java (inputMap_whenFocused): New InputMap. (inputMap_whenAncestorOfFocused): Likewise. (inputMap_whenInFocusedWindow): Likewise. (getActionForKeyStroke): Rewrite. (getConditionForKeystroke): Likewise. (ActionListenerProxy): New private class. (setInputMap): Implement. (getInputMap): Likewise. (setActionMap): Likewise. (getActionMap): Likewise. (processComponentKeyEvent): New empty method. (processKeyEvent): Implement. (processKeyBinding): Likewise. (resetKeyboardActions): Rewrite. * javax/swing/KeyStroke.java: Rewrite. * javax/swing/SwingUtilities.java (notifyAction): Implement. (replaceUIActionMap): Likewise. (replaceUIInputMap): Likewise. * javax/swing/plaf/basic/BasicButtonListener.java (focusGained): Implement. (focusLost): Repaint if focusPainted(). (installKeyboardActions): Install pressed / released actions. (uninstallKeyboardActions): Implement. * javax/swing/plaf/basic/BasicButtonUI.java (focusColor): New field. (installDefaults): Load focus color, install input map. (installKeyboardActions): Implement. (uninstallKeyboardActions): Likewise. (paintFocus): Rewrite. * javax/swing/plaf/basic/BasicLookAndFeel.java (Button.focus): New default, midPurple. * javax/swing/plaf/basic/BasicTextUI.java (kit): Make static. (installUI): Get doc from kit, load defaults. (getKeymapName): Implement. (createKeymap): Likewise. (installKeyboardActions): Likewise. (getInputMap): Likewise. (getActionMap): Likewise. (createActionMap): Likewise. * javax/swing/text/AbstractDocument.java (getStartPosition): Implement. (getEndPosition): Likewise. * javax/swing/text/DefaultEditorKit.java (CopyAction): New class. (CutAction): Likewise. (DefaultKeyTypedAction): Likewise. (InsertBreakAction): Likewise. (InsertContentAction): Likewise. (InsertTabAction): Likewise. (PasteAction): Likewise. (defaultActions): New static table. (createCaret): Implement. (getActions): Likewise. * javax/swing/text/JTextComponent.java (KeymapWrapper): New private class. (KeymapActionMap): Likewise. (DefaultKeymap): New class. (keymaps): New static table. (keymap): New field. (getKeymap): Implement. (removeKeymap): Likewise. (addKeymap): Likewise. (setKeymap): Likewise. (loadKeymap): Likewise. (getActions): Likewise. (margin): New field. (JTextComponent): Build and install default keymap. * javax/swing/text/TextAction.java (textAction): Call super properly. (getTextComponent): Implement. * javax/swing/text/Utilities.java (drawTabbedText): Adjust position by ascent. 2004-08-31 David Jee <djee@redhat.com> PR AWT/17156 * gnu/java/awt/peer/gtk/GtkMenuItemPeer.java (setEnabled): Make it a native method. * java/awt/DefaultKeyboardFocusManager.java (postProcessKeyEvent): Only post event if the menu item is active. * java/awt/MenuItem.java: Private field 'enabled' should be true by default. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuItemPeer.c (setEnabled): New function. 2004-08-31 David Jee <djee@redhat.com> PR AWT/17059 * gnu/java/awt/peer/gtk/GtkMenuBarPeer.java (nativeSetHelpMenu): New native method declaration. (addHelpMenu): Call nativeSetHelpMenu(). (addMenu): Remove. * java/awt/MenuBar.java (setHelpMenu): Call addNotify() on the new help menu. (add): Call addNotify() on the new menu. (addNotify): Set the help menu if one exists. * java/awt/peer/MenuBarPeer.java (addMenu): Remove. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuBarPeer.c (nativeSetHelpMenu): New method. 2004-08-31 Graydon Hoare <graydon@redhat.com> * Makefile.am: Add new files. * Makefile.in: Regenerate. * javax/swing/Box.java: Fix setting of layout in ctor. * javax/swing/JScrollPane.java: Scroll headers as well. * javax/swing/JTable.java: Reimplement. * javax/swing/JViewPort.java: Only add non-null children. * javax/swing/ScrollPaneLayout.java: Correct header calculations. * javax/swing/Timer.java: Fix stopping null waker. * javax/swing/plaf/basic/BasicTableHeaderUI.java: New file. * javax/swing/plaf/basic/BasicTableUI.java: New file. * javax/swing/table/DefaultTableCellRenderer.java: Configure. * javax/swing/table/DefaultTableColumnModel.java: Flesh out. * javax/swing/table/DefaultTableModel.java: Clean up. * javax/swing/table/JTableHeader.java: Implement. 2004-08-31 Mark Wielaard <mark@klomp.org> * javax/swing/JSpinner.java (getChangeListeners): Remove double semi-colon. 2004-08-31 Mark Wielaard <mark@klomp.org> * jni/gtk-peer/gnu_java_awt_peer_gtk_GdkClasspathFontPeerMetrics.c: Declare variables at top of functions/block. * jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c: Likewise. 2004-08-31 Mark Wielaard <mark@klomp.org> * java/lang/Rectangle.java (intersects): Check r.width and r.height first. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/text/PlainView.java (selectedColor): New field. (unselectedColor): Likewise. (font): Likewise. (updateMetrics): New method. (lineToRect): Likewise. (modelToView): Likewise. (drawSelectedText): Use color from JTextComponent ad draw with Utilities class. (drawUnselectedText): Likewise. (paint): Initialize helper fields. * javax/swing/text/View.java (getChildAllocation): New method. (getViewIndex): Likewise. (getToolTipText): Likewise. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/text/Utilities.java (drawTabbedText): Reimplemented. (getTabbedTextWidth): Likewise. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicTextUI.java (installDefaults): Install caret and highlighter. (modelToView): Use Bias.Forward when calling sibling. * javax/swing/text/AbstractDocument.java (ElementEdit): Implements DocumentEvent.ElementChange. (ElementEdit.ElementEdit): New method. (ElementEdit.getChildrenAdded): Likewise. (ElementEdit.getChildrenRemoved): Likewise. (ElementEdit.getElement): Likewise. (ElementEdit.getIndex): Likewise. * javax/swing/text/DefaultCaret.java (color): Removed. (textComponent): Renamed from parent, made private. (selectionVisible): Renamed from vis_sel, made private. (blinkRate): Renamed from blink, made private. (magicCaretPosition): Renamed from magic, made private. (visible): Renamed from vis, made private. (dot): Made private. (mark): Likewise. (deinstall): Remove as MouseMotionListener. (install): Initialize textComponent first. Add as MouseMotionListener. (paint): Reimplemented. * javax/swing/text/JTextComponent.java (setCaret): Deinstall old caret, install new one and fire property change after setting property. (setHighlighter): Deinstall old highlighter, install new one and fire property change after setting property. (setCaretColor): Fire property change after setting property. (setDisabledTextColor): Likewise. (setSelectedTextColor): Likewise. (setSelectionColor): Likewise. (modelToView): New method. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/text/AbstractDocument.java (getText): Simplified. * javax/swing/text/Segment.java (current): New field. (current): Reimplemented. (first): Likewise. (getIndex): Likewise. (last): Likewise. (next): Likewise. (previous): Likewise. (setIndex): Likewise. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicButtonUI.java (defaultTextIconGap): Made protected. (defaultTextShiftOffset): Likewise. (textShiftOffset): New field. (clearTextShiftOffset): New method. (getTextShiftOffset): Likewise. (setTextShiftOffset): Likewise. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicTextUI.java (installUI): Add eventHandler as property listener. (uninstallUI): remove eventHandler as propert listener. (installDefaults): Added comment. (installListeners): Likewise. (installKeyboardActions): Likewise. (uninstallDefaults): Likewise. (uninstallListeners): Likewise. (uninstallKeyboardActions): Likewise. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/text/AbstractDocument.java: Fixed some typos in comments. (insertString): Reimplemented. (remove): Likewise. (replace): New method. (children): Dont use fully qualified class name. (DefaultDocumentEvent.offset): Renamed from off. (DefaultDocumentEvent.length): Renamed from len. (DefaultDocumentEvent.type): New field. (DefaultDocumentEvent.DefaultDocumentEvent): New constructor. (DefaultDocumentEvent.getType): Implemented. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicTextUI.java (RootView.textComponent): Removed. (RootView.RootView): Don't initialize textComponent. (RootView.getViewFactory): New method. (EventHandler): New inner class. (rootView): Initialize at instance creation. (eventHandler): New field. (installUI): Don't create view hierarchy directly, call modelChanged() instead. (modelChanged): New method. * javax/swing/text/JTextComponent.java (setDocument): Fire property change event. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicTextUI.java (RootView.paint): Removed debug output. (paintSafely): Draw highlighter before text. (paintBackground): Use background color of text component. * javax/swing/plaf/basic/BasicToggleButtonUI.java: Reformatted. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicToolBarUI.java (BasicToolBarUI): Fixed arguments for constructor. (createUI): Fixed creation of object. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/DefaultListSelectionModel.java (fireValueChanged): Renamed from fireSelectionValueChanged, made protected. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/text/TabSet.java (TabSet): Implements java.io.Serializable. * javax/swing/text/TabStop.java (TabStop): Implements java.io.Serializable. (TabStop): Made public. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/JComponent.java (setUI): Fire PropertyChange. * javax/swing/JLabel.java (text): Renamed from labelText. (horizontalAlignment): New default vlaue. (icon): Renamed from activeIcon. (displayedMnemonic): Renamed from mnemonicKey, added default value. (displayedMnemonicIndex): Renamed from underlineChar. (setDisplayedMnemonic): Reimplemented. * javax/swing/JRadioButton.java (JRadioButton): New constructors. * javax/swing/JTextField.java (JTextField): Throw exception if colums < 0, initialitialz this.columns directly and initialize document with text conditionally. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicFormattedTextFieldUI.java, javax/swing/plaf/basic/BasicPasswordFieldUI.java, javax/swing/plaf/basic/BasicTextAreaUI.java: New files. * javax/swing/text/FieldView.java (paint): Just call super method for now. * Makefile.am: Added new files. * Makefile.in: Regenerated. 2004-08-31 Ka-Hing Cheung <kahing@javabsp.org> * javax/swing/AbstractSpinnerModel.java, javax/swing/JSpinner.java, javax/swing/SpinnerNumberModel.java, javax/swing/plaf/basic/BasicSpinnerUI.java: New files. * javax/swing/plaf/basic/BasicLookAndFeel.java (initClassDefaults): Added defaults for BasicSpinnerUI. 2004-08-31 Michael Koch <konqueror@gmx.de> * Makefile.am: Added new files. * Makefile.in: Regenerated. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/TransferHandler.java, javax/swing/plaf/basic/ComboPopup.java: New files * Makefile.am: Added javax/swing/TransferHandler.java and javax/swing/plaf/basic/ComboPopup.java * Makefile.in: Regenerated. 2004-08-31 Roman Kennke <roman@ontographics.com> * javax/swing/text/Utilities.java: New file. 2004-08-31 Michael Koch <konqueror@gmx.de> * Makefile.am: Added javax/swing/text/Utilities.java. * Makefile.in: Regenerated. 2004-08-31 Graydon Hoare <graydon@redhat.com> * javax/swing/text/SimpleAttributeSet.java: New file. * javax/swing/text/StyleConstants.java: New file. * javax/swing/text/StyleContext.java: New file. * javax/swing/text/TabSet.java: New file. * javax/swing/text/TabStop.java: New file. * javax/swing/text/AbstactDocument.java: (AbstractElement): Implement attribute support. * javax/swing/text/AttributeSet.java (NameAttribute): New static field. (ResolveAttribute): New static field. * Makefile.am: Update for new files. * Makefile.in: Regenerate. 2004-08-31 Craig Black <craig.black@aonix.com> * gnu/java/awt/peer/gtk/GdkGraphics.java (drawImage): Add support for scaling pixmaps. * jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics.c (copyAndScalePixmap): New native method. 2004-08-31 Thomas Fitzsimmons <fitzsim@redhat.com> PR AWT/16121 * jni/gtk-peer/gthread-jni.c: Include stdio.h. Eliminate type-punning compiler warnings using unions. (throw): Replace bzero with memset. 2004-08-31 Andreas Tobler <a.tobler@schweiz.ch> Thomas Fitzsimmons <fitzsim@redhat.com> * jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c: Move NSA_PB macros to gtkpeer.h. Include gtkpeer.h. * jni/gtk-peer/gtkpeer.h: Move NSA_PB macros here. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c (nativeSetIconImageFromDecoder): Use NSA_GET_PB_PTR macro. 2004-08-31 Mark Wielaard <mark@klomp.org> * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c: #include gdk.h, not gtk.h. #include jni.h, native_state.h, string.h and stdlib.h, not gtkpeer.h. (*vm): New static variable. (areaPreparedID): Make static. (areaUpdatedID): Likewise. (area_prepared): Get and use JNIEnv through stored JavaVM *vm. (area_prepared): Likewise. (area_updated): Likewise. (closed): Likewise. (initStaticState): Initialize *vm javaVM. (pumpBytes): Use given env, not global gdk_env. 2004-08-31 Mark Wielaard <mark@klomp.org> * java/awt/geom/CubicCurve2D.java (solveCubic): Removed duplicate comments. 2004-08-31 Sven de Marothy <sven@physto.se> * java/awt/geom/CubicCurve2D.java: Reindent. (contains): Implemented. (intersects): Implemented. * java/awt/geom/QuadCurve2D.java: Likewise. * java/awt/geom/GeneralPath.java: Reindent and document. Fully (re)implemented using separate xpoints and ypoints float[] coords. * java/awt/geom/RoundRectangle2D.java: Several bugfixes (Bug #6007). 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/JMenuItem.java (getMenuDragMouseListeners): New method. (getMenuKeyListeners): Likewise. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/AbstractButton.java (model): Made protected. (actionListener): Likewise. (changeListener): Likewise. (itemListener): Likewise. (multiClickThreshhold): New field. (getActionListeners): New method. (getChangeListeners): Likewise. (getItemListeners): Likewise. (fireItemStateChanged): Simplified implementation. (fireActionPerformed): Likewise. (fireStateChanged): Likewise. (getMultiClickThreshhold): New method. (setMultiClickThreshhold): Likewise. 2004-08-31 Tom Tromey <tromey@redhat.com> * java/awt/image/Kernel.java (clone): Use super.clone(). 2004-08-31 David Jee <djee@redhat.com> PR AWT/16682 * gnu/java/awt/peer/gtk/GtkFramePeer.java (nativeSetIconImage): Rename to nativeSetIconImageFromDecoder. (nativeSetIconImageFromData): New native method declaration. (setIconImage): Handle images not produced from GdkPixbufDecoder. * gnu/java/awt/peer/gtk/GtkImage.java (getPixelCache): New method. (getColorModel): New method. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c (nativeSetIconImage): Rename to nativeSetIconImageFromDecoder. (free_pixbuf_data): New helper function. (nativeSetIconImageFromData): New function. 2004-08-31 Graydon Hoare <graydon@redhat.com> PR SWING/16576 * javax/swing/JLayeredPane.java (setLayer): Permit changing layer after addition. (setPosition): Permit over-length positions. (layerToRange): Compare intValue()s. * javax/swing/Box.java (createHorizontalBox): Implement. (createRigidArea): Likewise. (createVerticalBox): Likewise. 2004-08-31 Kim Ho <kho@redhat.com> * java/awt/Component.java: (processMouseEvent): Consume event after listeners process it. (processMouseMotionEvent): ditto. (processMouseWheelEvent): ditto. * java/awt/Container.java: (acquireComponentForMouseEvent): Do not dispatch to events that have been removed from the Container. (handleEvent): Consume the MouseEvents. * javax/swing/RepaintManager.java: (paintDirtyRegions): Do not add to list of damaged areas if the component has no root. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicMenuItemUI.java: Clean ip imports. 2004-08-31 Mark Wielaard <mark@klomp.org> * gnu/java/awt/peer/gtk/GtkToolkit.java (getFontPeer): Don't return null when a MissingResourceException is thrown. Should never happen. 2004-08-31 Mark Wielaard <mark@klomp.org> * java/awt/EventQueue.java (postEvent): Throw NullPointerException when argument is null. 2004-08-31 Mark Wielaard <mark@klomp.org> * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c (Java_gnu_java_awt_peer_gtk_GtkComponentPeer_addExposeFilter): Define hid at start of function. (Java_gnu_java_awt_peer_gtk_GtkComponentPeer_removeExposeFilter): Likewise. 2004-08-31 Mark Wielaard <mark@klomp.org> * gnu/java/awt/EmbeddedWindow.java: Reindent. * javax/swing/JButton.java: Reindent. * javax/swing/JCheckBox.java: Reindent. 2004-08-31 Mark Wielaard <mark@klomp.org> * Makefile.am (gtk_c_source_files): Added jni/gtk-peer/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c. (gtk_awt_peer_sources): Added gnu/java/awt/peer/gtk/GThreadMutex.java and gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java. * Makefile.in: Regenerated. 2004-08-31 Archie Cobbs <archie@dellroad.org> * jni/gtk-peer/gthread-jni.c: don't #include nonexistent files 2004-08-31 Steven Augart <augart@watson.ibm.com> * jni/gtk-peer/gthread-jni.c (c-font-lock-extra-types): Added jfieldID, jmethodID. 2004-08-31 Mark Wielaard <mark@klomp.org> * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c (Java_gnu_java_awt_peer_gtk_GtkMainThread_gtkInit): Initialize gdk_env before calling any gdk or gtk function. * gnu/java/awt/peer/gtk/GtkMainThread.java (gtkInitCalled): New field. (GtkMainThread): Call wait() in while loop waiting for gtkInitCalled. (run): Set gtkInitCalled. 2004-08-31 Steven Augart <augart@watson.ibm.com> * gnu/java/awt/peer/gtk/GtkMainThread.java (run): Pass the value of the gnu.classpath.awt.gtk.portable.native.sync system property to C. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c (Java_gnu_java_awt_peer_gtk_GtkMainThread_gtkInit): New argument, portableNativeSync. Delegate PORTABLE_NATIVE_SYNC work to init_glib_threads. (init_glib_threads): New function. 2004-08-31 Mark Wielaard <mark@klomp.org> * jni/gtk-peer/gthread-jni.c: Define MIN_, MAX_ and NORM_ PRIORITY when not already defined in header file. 2004-08-31 Mark Wielaard <mark@klomp.org> * jni/gtk-peer/gthread-jni.c (setup_cache): Call ExceptionOccurred, not ExceptionCheck, when we don't have JNI 1.2. 2004-08-31 Steven Augart <augart@watson.ibm.com> * gnu/native/jni/gtk-peer/gthread-jni.c: Indentation fixes. Implemented missing functions for GTK2. Added error handling. Renamed static functions out of the g_ namespace. Added TRACE_API_CALLS, EXPLAIN_TROUBLE, EXPLAIN_BROKEN, EXPLAIN_BADLY_BROKEN, and DELETE_LOCAL_REFS options. Rewrote global-reference code. Eliminated cascading errors. (mutex_trylock_jni_impl) Fully implemented. (cond_timed_wait_jni_impl) Went from millisecond to microsecond resolution. (setup_cache) New function. (mutex_cond_wait_jni_impl, mutex_cond_timed_wait_jni_impl) Fixed bug where they were not unlocking the GMutex associated with the condition variable during the wait on that condition variable. * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c, native/jni/gtk-peer/gthread-jni.c, native/jni/gtk-peer/gthread-jni.h (g_thread_jni_functions): Renamed to ... (portable_native_sync_jni_functions): this name. (gdk_vm): Renamed to... (the_vm): this name. * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c (gdk_vm): Removed duplicate definition. (gtkInit): Removed stray message to stdout. (gtkInit): Use g_malloc and g_free instead of malloc and free. (gtkInit): Fix a const assignment bug. (gtkInit): Simplified code. * gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java, native/jni/gtk-peer/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c, native/jni/gtk-peer/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.h, gnu/java/awt/peer/gtk/GThreadMutex.java: New files. 2004-08-31 Mark Wielaard <mark@klomp.org> * javax/swing/Box.java: Put FIXME comment above class declaration. * javax/swing/JButton.java: Remove illegal L&F HTML from comments. * javax/swing/JCheckBox.java: Likewise. * javax/swing/JDialog.java: Likewise. * javax/swing/JRadioButton.java: Likewise. * javax/swing/JToggleButton.java: Likewise. * javax/swing/UIManager.java: Likewise. * javax/swing/border/TitledBorder.java: Likewise. * javax/swing/plaf/basic/BasicLabelUI.java: Likewise. * javax/swing/plaf/basic/BasicLookAndFeel.java: Likewise. * javax/swing/plaf/basic/BasicPopupMenuSeparatorUI.java: Likewise. * javax/swing/plaf/basic/BasicProgressBarUI.java: Likewise. * javax/swing/plaf/basic/BasicScrollBarUI.java: Likewise. * javax/swing/plaf/basic/BasicSeparatorUI.java: Likewise. * javax/swing/text/JTextComponent.java: Likewise. 2004-08-31 David Jee <djee@redhat.com> PR AWT/16682 * gnu/java/awt/peer/gtk/GtkFramePeer.java (setIconImage): Add a FIXME for unhandled cases. 2004-08-31 Thomas Fitzsimmons <fitzsim@redhat.com> PR AWT/16040 * gnu/awt/LightweightRedirector.java: Call getModifiersEx, not getModifiers. Replace old button masks with new ones. * gnu/awt/xlib/XEventLoop.java: Likewise. * gnu/java/awt/peer/gtk/GtkButtonPeer.java: Likewise. * gnu/java/awt/peer/gtk/GtkComponentPeer.java, jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c: Likewise. * gnu/java/awt/peer/gtk/GtkListPeer.java: Likewise. * gnu/java/awt/peer/gtk/GtkTextFieldPeer.java: Likewise. * java/awt/AWTKeyStroke.java: Remove old modifier masks. * java/awt/Component.java: Replace old modifier masks with new ones. * java/awt/Container.java: Call getModifiersEx, not getModifiers. * java/awt/DefaultKeyboardFocusManager.java: Likewise. Remove old modifier masks. * javax/swing/JMenuItem.java: Replace old button masks with new ones. * javax/swing/KeyStroke.java: Call getModifiersEx, not getModifiers. * javax/swing/SwingUtilities.java: Likewise. * javax/swing/plaf/basic/BasicButtonListener.java: Likewise. * javax/swing/plaf/basic/BasicInternalFrameUI.java: Likewise. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c: Replace old mask macros with new ones. * jni/gtk-peer/gtkpeer.h: Replace old button and modifier mask macros with new ones representing new masks. 2004-08-31 Craig Black <craig.black@aonix.com> * gnu/java/awt/peer/gtk/GdkGraphics.java (drawRoundRect): Implemented. (fillRoundRect): Implemented. * gnu/java/awt/peer/gtk/GdkGraphics2D.java (drawRoundRect): Reimplemented to match GdkGraphics. (fillRoundRect): Reimplemented to match GdkGraphics. 2004-08-31 Mark Wielaard <mark@klomp.org> * Makefile.in: Regenerated. 2004-08-31 Michael Koch <konqueror@gmx.de> * gnu/java/awt/EmbeddedWindow.java (addNotify): Use AccessController to allow execution of privileged code. 2004-08-31 Michael Koch <konqueror@gmx.de> * gnu/java/awt/EmbeddedWindow.java (static): Removed. (addNotify): Set peer via reflection. (setWindowPeer): Removed. * gnu/java/awt/natEmbeddedWindow.cc: Removed. * Makefile.am (nat_source_files): Removed gnu/java/awt/natEmbeddedWindow.cc. 2004-08-31 Bryce McKinlay <mckinlay@redhat.com> * Makefile.am: Add gnu/java/security/action/GetPropertyAction.java and gnu/java/security/action/SetAccessibleAction.java. 2004-08-31 Bryce McKinlay <mckinlay@redhat.com> * gnu/java/security/action/GetPropertyAction.java (setParameters): Renamed from 'setName'. New 2-argument form with default value. (run): Pass default 'value' parameter to System.getProperty(). * gnu/java/security/action/SetAccessibleAction.java: Fix javadoc typos. 2004-08-31 Bryce McKinlay <mckinlay@redhat.com> * gnu/java/security/action/GetPropertyAction.java: New class. * gnu/java/security/action/SetAccessibleAction.java: New class. 2004-08-31 David Jee <djee@redhat.com> * gnu/java/awt/peer/gtk/GtkFramePeer.java (setIconImage): Check if image is null. 2004-08-31 David Jee <djee@redhat.com> * gnu/java/awt/peer/gtk/GtkFramePeer.java (create): Set the icon image. (nativeSetIconImage): New native method declaration. (setIconImage): Implement. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c (nativeSetIconImage): New function. 2004-08-31 Dalibor Topic <robilad@kaffe.org> * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFileDialogPeer.c (filenameFilterCallback): Declare local variable accepted before use. 2004-08-31 Dalibor Topic <robilad@kaffe.org> * gnu/java/awt/ComponentDataBlitOp.java: Cleaned up imports. 2004-08-31 Tom Tromey <tromey@redhat.com> * gnu/java/awt/peer/GLightweightPeer.java, gnu/java/awt/peer/gtk/GdkGraphics2D.java, gnu/java/awt/peer/gtk/GtkComponentPeer.java, javax/swing/JScrollPane.java: Removed redundant imports. 2004-08-31 David Jee <djee@redhat.com> * java/awt/DefaultKeyboardFocusManager.java (postProcessKeyEvent): Only activate MenuShortcuts on KEY_PRESSED event. Fix shift modifier checking. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuPeer.c (accel_attach): Remove. (setupAccelGroup): Remove calls to accel_attach. 2004-08-31 Thomas Fitzsimmons <fitzsim@redhat.com> * gnu/java/awt/peer/gtk/GtkArg.java: Remove file. * gnu/java/awt/peer/gtk/GtkArgList.java: Remove file. * Makefile.am (gtk_awt_peer_sources): Remove GtkArg.java and GtkArgList.java. (gtk_c_files): Use CAIRO_CFLAGS and PANGOFT2_CFLAGS, not _LIBS. * Makefile.in: Regenerate. * gnu/java/awt/peer/gtk/GtkButtonPeer.java, jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c (create(String)): New method. (create): Call new create method. (getArgs): Remove method. * gnu/java/awt/peer/gtk/GtkCheckboxPeer.java, jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c (nativeCreate): Rename to create. (gtkSetLabel): Rename to gtkButtonSetLabel. (gtkToggleButtonSetActive): New method. (create): Call gtkToggleButtonSetActive and gtkButtonSetLabel. (setState): Replace set call with gtkToggleButtonSetActive. (setLabel): Replace gtkSetLabel call with gtkButtonSetLabel. (getArgs): Remove method. * gnu/java/awt/peer/gtk/GtkComponentPeer.java, jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c (gtkWidgetSetSensitive): New method. (gtkWidgetSetParent): Likewise. (GtkComponentPeer): Call setParent, setComponentBounds and setVisibleAndEnabled. (setParent): New method. (setComponentBounds): New method. (setVisibleAndEnabled): New method. (setEnabled): Call gtkWidgetSetSensitive. (getArgs): Remove method. Remove all set methods. * gnu/java/awt/peer/gtk/GtkDialogPeer.java (create): Call gtkWindowSetModal, setTitle and setResizable. (getArgs): Remove method. * gnu/java/awt/peer/gtk/GtkFileDialogPeer.java (setComponentBounds): New method. * gnu/java/awt/peer/gtk/GtkFramePeer.java (setResizable): Replace set call with gtkWindowSetResizable. (getArgs): Remove method. (create): Call setTitle and setResizable. * gnu/java/awt/peer/gtk/GtkWindowPeer.java, jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c (gtkWindowSetTitle): New method. (gtkWindowSetResizable): New method. (gtkWindowSetModal): New method. (setParent): New method. (setVisibleAndEnabled): New method. (getArgs): Remove method. (setTitle): Call gtkWindowSetTitle. (setResizable): Call gtkWindowSetResizable. * jni/gtk-peer/gtkpeer.h [DEBUG_LOCKING]: New define to turn on and off locking instrumentation. 2004-08-31 Kim Ho <kho@redhat.com> * Makefile.am: Add new file. * Makefile.in: Regenerate. * gcj/Makefile.in: Regenerate * include/Makefile.in: * java/awt/Container.java: (acquireComponentForMouseEvent): Respect the event mask when looking for candidate. * javax/swing/JComponent.java: Remove toolTip field. (createToolTip): Create a tooltip on demand. (setToolTipText): Register with the ToolTipManager. (getToolTipText(MouseEvent)): Return getToolTipText(). * javax/swing/JToolTip.java: Implement. * javax/swing/Timer.java: Jalopy. (restart): Call stop, then start. (stop): Interrupt the timer rather than wait for the timer to come to a stop naturally. * javax/swing/ToolTipManager.java: Implement. * javax/swing/plaf/basic/BasicLookAndFeel.java: Change ToolTip.background color. * javax/swing/plaf/basic/BasicToolTipUI.java: Implement. * testsuite/Makefile.in: Regenerate 2004-08-31 Jerry Quinn <jlquinn@optonline.net> * java/awt/image/DirectColorModel.java (DirectColorModel): Fix constructor param comments. 2004-08-31 Thomas Fitzsimmons <fitzsim@redhat.com> * java/awt/Component.java: Document AWT 1.0 event handler methods. 2004-08-31 Roman Kennke <roman@ontographics.com> * javax/swing/Box.java: (createGlue): Implemented (createHorizontalGlue): Implemented (createHorizontalStrut): Implemented (createVerticalGlue): Implemented (createVerticalStrut): Implemented 2004-08-31 David Jee <djee@redhat.com> * gnu/java/awt/peer/gtk/GtkChoicePeer.java (GtkChoicePeer): Do not automatically select first item. (getHistory): Remove. (nativeGetSelected): New method. (nativeRemoveAll): New method. (add): Use nativeGetSelected() instead of getHistory(). (remove): Likewise. (removeAll): Call nativeRemoveAll(). * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c (create): Migrate to GtkComboBox. (append): Likewise. (nativeAdd): Likewise. (nativeRemove): Likewise. (select): Likewise. (nativeRemoveAll): New method. (nativeGetSelected): New method. (selection_changed): New method. (getHistory): Remove. (item_activate): Remove. (item_removed): Remove. (connect_choice_item_selectable_hook): Remove. 2004-08-31 Thomas Fitzsimmons <fitzsim@redhat.com> * gnu/java/awt/peer/gtk/GtkTextFieldPeer.java (create): Use tf variable in setEditable call. * gnu/java/awt/peer/gtk/GtkTextFieldPeer.java, jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextFieldPeer.c (gtkWidgetSetBackground): New method. (gtkWidgetSetForeground): Likewise. (create): Set peer's editable state based on awtComponent's. * java/awt/Button.java (Button()): Use empty string rather than null in no-label constructor. 2004-08-31 Roman Kennke <roman@ontographics.com> * javax/swing/BoxLayout.java: Reimplement. 2004-08-31 Thomas Fitzsimmons <fitzsim@redhat.com> * gnu/java/awt/peer/gtk/GdkGraphics.java, gnu_java_awt_peer_gtk_GdkGraphics.c (initState(GtkComponentPeer)): Don't return array of colour values. (GdkGraphics(int,int)): Set default font to size 12. (GdkGraphics(GtkComponentPeer)): Set graphics colour to component's foreground colour. * gnu/java/awt/peer/gtk/GdkGraphics2D.java, gnu_java_awt_peer_gtk_GdkGraphics2D.c (initState(GtkComponentPeer)): Don't return array of colour values. (GdkGraphics2D(GtkComponentPeer)): Set foreground and background colours to component's colours. (current_colors_of_widget): Remove function. * gnu/java/awt/peer/gtk/GtkOffScreenImage.java (getGraphics): Return a new graphics object. * java/awt/Font.java (toString): Fix format. * java/awt/Graphics.java (toString): Likewise. 2004-08-31 Craig Black <craig.black@aonix.com> * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuPeer.c (addTearOff): New function. * gnu/java/awt/peer/gtk/GtkMenuPeer.java (addTearOff): New native method. (init): Call addTearOff() when menu.isTearOff(). 2004-08-31 Bryce McKinlay <mckinlay@redhat.com> * gnu/java/awt/ClasspathToolkit.java (createImageProducer): New. Default implementation. * gnu/java/awt/peer/gtk/GtkToolkit.java (createImageProducer): New. Implement using GdkPixbufDecoder. 2004-08-31 David Jee <djee@redhat.com> * gnu/java/awt/peer/gtk/GtkComponentPeer.java (GtkComponentPeer): Use gtkWidgetGetPreferredDimensions() for setting the size of GtkFileDialogPeers. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c (gtkWidgetGetPreferredDimensions): For widgets extending GtkWindow, use their default sizes rather than their natural requisitions. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/JFormattedTextField.java (JFormattedTextField): Implemented. * javax/swing/text/DefaultEditorKit.java (BeepAction): New inner class. * javax/swing/text/Segment.java (partialReturn): New field. (setPartialReturn): New method. (isPartialReturn): Likewise. * javax/swing/text/View.java (createFragment): Fixed typo. (getStartOffset): New method. (getEndOffset): Likewise. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/table/DefaultTableColumnModel.java (serialVersionUID): Made private. (listenerList): Initialize. (changeEvent): Initialize. * javax/swing/table/JTableHeader.java (JTableHeader): New constructors. (createDefaultColumnModel): New method. * javax/swing/table/TableColumn.java (setHeaderRenderer): Simplified code. (setCellRenderer): Likewise. (setWidth): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@86956 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava/jni')
-rw-r--r--libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkClasspathFontPeerMetrics.c6
-rw-r--r--libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics.c117
-rw-r--r--libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c66
-rw-r--r--libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c87
-rw-r--r--libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c19
-rw-r--r--libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c36
-rw-r--r--libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c187
-rw-r--r--libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c250
-rw-r--r--libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c54
-rw-r--r--libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFileDialogPeer.c3
-rw-r--r--libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c81
-rw-r--r--libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuBarPeer.c23
-rw-r--r--libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuItemPeer.c12
-rw-r--r--libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuPeer.c40
-rw-r--r--libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextComponentPeer.c1
-rw-r--r--libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextFieldPeer.c41
-rw-r--r--libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c117
-rw-r--r--libjava/jni/gtk-peer/gthread-jni.c2653
-rw-r--r--libjava/jni/gtk-peer/gthread-jni.h4
-rw-r--r--libjava/jni/gtk-peer/gtkpeer.h43
20 files changed, 3054 insertions, 786 deletions
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkClasspathFontPeerMetrics.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkClasspathFontPeerMetrics.c
index cc09102debd..c10b945ab6b 100644
--- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkClasspathFontPeerMetrics.c
+++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkClasspathFontPeerMetrics.c
@@ -54,6 +54,8 @@ JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_GdkClasspathFontPeerMetri
jint *metrics;
struct peerfont *pf = NULL;
FT_Matrix mat;
+ double pointsize;
+ FT_Face face;
pf = NSA_GET_FONT_PTR(env, font);
g_assert (pf != NULL);
@@ -68,7 +70,7 @@ JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_GdkClasspathFontPeerMetri
#define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
#define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0)
- double pointsize = pango_font_description_get_size (pf->desc);
+ pointsize = pango_font_description_get_size (pf->desc);
pointsize /= (double) PANGO_SCALE;
mat.xx = DOUBLE_TO_16_16(1);
@@ -76,7 +78,7 @@ JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_GdkClasspathFontPeerMetri
mat.yx = DOUBLE_TO_16_16(0);
mat.yy = DOUBLE_TO_16_16(1);
- FT_Face face = pango_ft2_font_get_face (pf->font);
+ face = pango_ft2_font_get_face (pf->font);
FT_Set_Transform(face, &mat, NULL);
FT_Set_Char_Size( face,
DOUBLE_TO_26_6 (pointsize),
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics.c
index 864e465871b..a79ed5eb093 100644
--- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics.c
+++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics.c
@@ -94,15 +94,13 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics_initState__II
/* copy the native state of the peer (GtkWidget *) to the native state
of the graphics object */
-JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics_initState__Lgnu_java_awt_peer_gtk_GtkComponentPeer_2
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics_initState__Lgnu_java_awt_peer_gtk_GtkComponentPeer_2
(JNIEnv *env, jobject obj, jobject peer)
{
struct graphics *g = (struct graphics *) malloc (sizeof (struct graphics));
void *ptr;
GtkWidget *widget;
GdkColor color;
- jintArray array;
- jint *rgb;
ptr = NSA_GET_PTR (env, peer);
g->x_offset = g->y_offset = 0;
@@ -133,16 +131,7 @@ JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics_initState__Lg
gdk_threads_leave ();
- array = (*env)->NewIntArray (env, 3);
- rgb = (*env)->GetIntArrayElements (env, array, NULL);
- rgb[0] = color.red >> 8;
- rgb[1] = color.green >> 8;
- rgb[2] = color.blue >> 8;
- (*env)->ReleaseIntArrayElements (env, array, rgb, 0);
-
NSA_SET_PTR (env, obj, g);
-
- return array;
}
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics_dispose
@@ -323,7 +312,111 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics_copyPixmap
gdk_flush ();
gdk_threads_leave ();
}
+
+static void flip_pixbuf (GdkPixbuf *pixbuf,
+ jboolean flip_x,
+ jboolean flip_y,
+ jint width,
+ jint height)
+{
+ gint src_rs;
+ guchar *src_pix;
+
+ src_rs = gdk_pixbuf_get_rowstride (pixbuf);
+ src_pix = gdk_pixbuf_get_pixels (pixbuf);
+
+ if (flip_x)
+ {
+ gint i, channels;
+ guchar buf[4];
+
+ channels = gdk_pixbuf_get_has_alpha (pixbuf) ? 4 : 3;
+
+ for (i = 0; i < height; i++)
+ {
+ guchar *left = src_pix + i * src_rs;
+ guchar *right = left + channels * (width - 1);
+ while (left < right)
+ {
+ g_memmove (buf, left, channels);
+ g_memmove (left, right, channels);
+ g_memmove (right, buf, channels);
+ left += channels;
+ right -= channels;
+ }
+ }
+ }
+
+ if (flip_y)
+ {
+ guchar *top = src_pix;
+ guchar *bottom = top + (height - 1) * src_rs;
+ gpointer buf = g_malloc (src_rs);
+
+ while (top < bottom)
+ {
+ g_memmove (buf, top, src_rs);
+ g_memmove (top, bottom, src_rs);
+ g_memmove (bottom, buf, src_rs);
+ top += src_rs;
+ bottom -= src_rs;
+ }
+
+ g_free (buf);
+ }
+}
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics_copyAndScalePixmap
+ (JNIEnv *env, jobject obj, jobject offscreen, jboolean flip_x, jboolean flip_y,
+ jint src_x, jint src_y, jint src_width, jint src_height,
+ jint dest_x, jint dest_y, jint dest_width, jint dest_height)
+{
+ struct graphics *g1, *g2;
+ GdkPixbuf *buf_src, *buf_dest;
+
+ g1 = (struct graphics *) NSA_GET_PTR (env, obj);
+ g2 = (struct graphics *) NSA_GET_PTR (env, offscreen);
+
+ gdk_threads_enter ();
+
+ buf_src = gdk_pixbuf_get_from_drawable (NULL,
+ g2->drawable,
+ g2->cm,
+ src_x,
+ src_y,
+ 0,
+ 0,
+ src_width,
+ src_height);
+
+ buf_dest = gdk_pixbuf_scale_simple (buf_src,
+ dest_width,
+ dest_height,
+ GDK_INTERP_BILINEAR);
+
+ if (flip_x || flip_y)
+ {
+ flip_pixbuf (buf_dest, flip_x, flip_y, dest_width, dest_height);
+ }
+
+ gdk_pixbuf_render_to_drawable (buf_dest,
+ g1->drawable,
+ g1->gc,
+ 0,
+ 0,
+ dest_x,
+ dest_y,
+ dest_width,
+ dest_height,
+ GDK_RGB_DITHER_NORMAL,
+ 0,
+ 0);
+
+ g_object_unref (G_OBJECT (buf_src));
+ g_object_unref (G_OBJECT (buf_dest));
+
+ gdk_threads_leave ();
+}
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c
index 733461dcfc1..e4d223c543d 100644
--- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c
+++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c
@@ -400,7 +400,6 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_gdkDrawDrawable
struct graphics2d *src = NULL, *dst = NULL;
gint s_height, s_width, d_height, d_width, height, width;
cairo_matrix_t *matrix;
- GdkGC *gc;
cairo_operator_t tmp_op;
gdk_threads_enter();
@@ -443,41 +442,12 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_gdkDrawDrawable
gdk_threads_leave();
}
-static jintArray
-current_colors_of_widget (GtkWidget *widget, JNIEnv *env)
-{
- GdkColor color;
- jintArray array;
- jint *rgb;
-
- g_assert (widget != NULL);
- g_assert (env != NULL);
-
- color = widget->style->fg[GTK_STATE_NORMAL];
- array = (*env)->NewIntArray (env, 6);
-
- rgb = (*env)->GetIntArrayElements (env, array, NULL);
- rgb[0] = color.red >> 8;
- rgb[1] = color.green >> 8;
- rgb[2] = color.blue >> 8;
-
- color = widget->style->bg[GTK_STATE_NORMAL];
- rgb[3] = color.red >> 8;
- rgb[4] = color.green >> 8;
- rgb[5] = color.blue >> 8;
-
- (*env)->ReleaseIntArrayElements (env, array, rgb, 0);
-
- return array;
-}
-
-JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__Lgnu_java_awt_peer_gtk_GtkComponentPeer_2
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__Lgnu_java_awt_peer_gtk_GtkComponentPeer_2
(JNIEnv *env, jobject obj, jobject peer)
{
struct graphics2d *gr = NULL;
GtkWidget *widget = NULL;
void *ptr = NULL;
- jintArray color;
gdk_threads_enter();
if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
@@ -504,11 +474,8 @@ JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__
else
init_graphics2d_as_pixbuf (gr);
- color = current_colors_of_widget (widget, env);
-
NSA_SET_G2D_PTR (env, obj, gr);
gdk_threads_leave();
- return color;
}
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_dispose
@@ -637,20 +604,21 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_setGradient
negate offsets. oh well.
*/
-
- double a = (x2 - x1 == 0.) ? 0. : ((cyclic ? 3.0 : 2.0) / (x2 - x1));
- double c = (y2 - y1 == 0.) ? 0. : (1. / (y2 - y1));
- double dx = (x1 == 0.) ? 0. : 1. / x1;
- double dy = (y1 == 0.) ? 0. : 1. / y1;
-
- cairo_matrix_set_affine (mat,
- a, 0.,
- c, 0.,
- dx, dy);
-
- cairo_surface_set_matrix (surf, mat);
- cairo_matrix_destroy (mat);
- cairo_surface_set_filter (surf, CAIRO_FILTER_BILINEAR);
+ {
+ double a = (x2 - x1 == 0.) ? 0. : ((cyclic ? 3.0 : 2.0) / (x2 - x1));
+ double c = (y2 - y1 == 0.) ? 0. : (1. / (y2 - y1));
+ double dx = (x1 == 0.) ? 0. : 1. / x1;
+ double dy = (y1 == 0.) ? 0. : 1. / y1;
+
+ cairo_matrix_set_affine (mat,
+ a, 0.,
+ c, 0.,
+ dx, dy);
+
+ cairo_surface_set_matrix (surf, mat);
+ cairo_matrix_destroy (mat);
+ cairo_surface_set_filter (surf, CAIRO_FILTER_BILINEAR);
+ }
/* FIXME: repeating gradients (not to mention hold gradients) don't seem to work. */
/* cairo_surface_set_repeat (surf, cyclic ? 1 : 0); */
@@ -783,7 +751,7 @@ JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_getImagePix
jint i, px;
gdk_threads_enter();
- if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; }
+ if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return NULL; }
gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
g_assert (gr != NULL);
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c
index 97e49625cb7..f58c289aa40 100644
--- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c
+++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c
@@ -1,5 +1,5 @@
/* gdkpixbufdecoder.c
- Copyright (C) 1999, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2003, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -35,36 +35,38 @@
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
-
-#include <gtk/gtk.h>
+#include <gtkpeer.h>
+#include <gdk/gdk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gdk-pixbuf/gdk-pixbuf-loader.h>
-#include "gtkpeer.h"
+#include <jni.h>
+#include "native_state.h"
#include "gnu_java_awt_peer_gtk_GdkPixbufDecoder.h"
-struct state_table *native_pixbufdecoder_state_table;
-
-#define NSA_PB_INIT(env, clazz) \
- native_pixbufdecoder_state_table = init_state_table (env, clazz)
+#include <string.h>
+#include <stdlib.h>
-#define NSA_GET_PB_PTR(env, obj) \
- get_state (env, obj, native_pixbufdecoder_state_table)
-
-#define NSA_SET_PB_PTR(env, obj, ptr) \
- set_state (env, obj, native_pixbufdecoder_state_table, (void *)ptr)
+struct state_table *native_pixbufdecoder_state_table;
-#define NSA_DEL_PB_PTR(env, obj) \
- remove_state_slot (env, obj, native_pixbufdecoder_state_table)
+/* Union used for type punning. */
+union env_union
+{
+ void **void_env;
+ JNIEnv **jni_env;
+};
+static JavaVM *vm;
-jmethodID areaPreparedID;
-jmethodID areaUpdatedID;
+static jmethodID areaPreparedID;
+static jmethodID areaUpdatedID;
static void
area_prepared (GdkPixbufLoader *loader,
jobject *decoder)
{
+ JNIEnv *env;
+ union env_union e;
jint width, height;
GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
@@ -78,11 +80,13 @@ area_prepared (GdkPixbufLoader *loader,
g_assert (decoder != NULL);
- (*gdk_env)->CallVoidMethod (gdk_env,
- *decoder,
- areaPreparedID,
- width, height);
-
+ e.jni_env = &env;
+ (*vm)->GetEnv (vm, e.void_env, JNI_VERSION_1_1);
+ (*env)->CallVoidMethod (env,
+ *decoder,
+ areaPreparedID,
+ width, height);
+
gdk_threads_enter ();
}
@@ -92,6 +96,8 @@ area_updated (GdkPixbufLoader *loader,
gint width, gint height,
jobject *decoder)
{
+ JNIEnv *env;
+ union env_union e;
jint stride_bytes, stride_pixels, n_channels, n_pixels;
int i, px;
jintArray jpixels;
@@ -114,8 +120,10 @@ area_updated (GdkPixbufLoader *loader,
n_pixels = height * stride_pixels;
gdk_pixels = gdk_pixbuf_get_pixels (pixbuf);
- jpixels = (*gdk_env)->NewIntArray (gdk_env, n_pixels);
- java_pixels = (*gdk_env)->GetIntArrayElements (gdk_env, jpixels, NULL);
+ e.jni_env = &env;
+ (*vm)->GetEnv (vm, e.void_env, JNI_VERSION_1_1);
+ jpixels = (*env)->NewIntArray (env, n_pixels);
+ java_pixels = (*env)->GetIntArrayElements (env, jpixels, NULL);
memcpy (java_pixels,
gdk_pixels + (y * stride_bytes),
@@ -141,22 +149,27 @@ area_updated (GdkPixbufLoader *loader,
gdk_threads_leave ();
- (*gdk_env)->ReleaseIntArrayElements (gdk_env, jpixels, java_pixels, 0);
- (*gdk_env)->CallVoidMethod (gdk_env,
- *decoder,
- areaUpdatedID,
- (jint) x, (jint) y,
- (jint) width, (jint) height,
- jpixels,
- stride_pixels);
+ (*env)->ReleaseIntArrayElements (env, jpixels, java_pixels, 0);
+ (*env)->CallVoidMethod (env,
+ *decoder,
+ areaUpdatedID,
+ (jint) x, (jint) y,
+ (jint) width, (jint) height,
+ jpixels,
+ stride_pixels);
gdk_threads_enter ();
}
static void
closed (GdkPixbufLoader *loader __attribute__((unused)), jobject *decoder)
{
+ JNIEnv *env;
+ union env_union e;
+ e.jni_env = &env;
+ (*vm)->GetEnv (vm, e.void_env, JNI_VERSION_1_1);
+
gdk_threads_leave ();
- (*gdk_env)->DeleteGlobalRef (gdk_env, *decoder);
+ (*env)->DeleteGlobalRef (env, *decoder);
free (decoder);
gdk_threads_enter ();
}
@@ -187,6 +200,8 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_initState
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_initStaticState
(JNIEnv *env, jclass clazz)
{
+ (*env)->GetJavaVM(env, &vm);
+
areaPreparedID = (*env)->GetMethodID (env, clazz,
"areaPrepared",
"(II)V");
@@ -223,14 +238,14 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_pumpBytes
if (len < 1)
return;
- bytes = (*gdk_env)->GetByteArrayElements (gdk_env, jarr, NULL);
+ bytes = (*env)->GetByteArrayElements (env, jarr, NULL);
g_assert (bytes != NULL);
loader = (GdkPixbufLoader *)NSA_GET_PB_PTR (env, obj);
g_assert (loader != NULL);
gdk_threads_enter ();
- gdk_pixbuf_loader_write (loader, bytes, len, NULL);
+ gdk_pixbuf_loader_write (loader, (const guchar *) bytes, len, NULL);
gdk_threads_leave ();
- (*gdk_env)->ReleaseByteArrayElements (gdk_env, jarr, bytes, 0);
+ (*env)->ReleaseByteArrayElements (env, jarr, bytes, 0);
}
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c
index d9647e9ba10..08d38b5871d 100644
--- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c
+++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c
@@ -42,20 +42,23 @@ exception statement from your version. */
JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkButtonPeer_create
- (JNIEnv *env, jobject obj)
+ (JNIEnv *env, jobject obj, jstring label)
{
+ const char *c_label;
GtkWidget *button;
- /* Create global reference and save it for future use */
NSA_SET_GLOBAL_REF (env, obj);
+ c_label = (*env)->GetStringUTFChars (env, label, NULL);
+
gdk_threads_enter ();
-
- button = gtk_button_new();
+
+ button = gtk_button_new_with_label (c_label);
gtk_widget_show (button);
gdk_threads_leave ();
+ (*env)->ReleaseStringUTFChars (env, label, c_label);
NSA_SET_PTR (env, obj, button);
}
@@ -102,7 +105,7 @@ Java_gnu_java_awt_peer_gtk_GtkButtonPeer_gtkSetLabel
gdk_threads_enter ();
label = gtk_bin_get_child (GTK_BIN (ptr));
- gtk_label_set_text (GTK_LABEL(label), text);
+ gtk_label_set_text (GTK_LABEL (label), text);
gdk_threads_leave ();
@@ -126,9 +129,6 @@ Java_gnu_java_awt_peer_gtk_GtkButtonPeer_gtkSetFont
label = gtk_bin_get_child (GTK_BIN (ptr));
- if (!label)
- return;
-
font_desc = pango_font_description_from_string (font_name);
pango_font_description_set_size (font_desc, size * dpi_conversion_factor);
@@ -165,9 +165,6 @@ Java_gnu_java_awt_peer_gtk_GtkButtonPeer_gtkWidgetSetForeground
label = gtk_bin_get_child (GTK_BIN(ptr));
- if (!label)
- return;
-
gtk_widget_modify_fg (label, GTK_STATE_NORMAL, &color);
gtk_widget_modify_fg (label, GTK_STATE_ACTIVE, &color);
gtk_widget_modify_fg (label, GTK_STATE_PRELIGHT, &color);
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c
index f5d7cfb89aa..4d5c8114cd7 100644
--- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c
+++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c
@@ -43,12 +43,11 @@ exception statement from your version. */
static void item_toggled (GtkToggleButton *item, jobject peer);
JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_nativeCreate
- (JNIEnv *env, jobject obj, jobject group, jboolean state)
+Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_create
+ (JNIEnv *env, jobject obj, jobject group)
{
GtkWidget *button;
- /* Create global reference and save it for future use */
NSA_SET_GLOBAL_REF (env, obj);
gdk_threads_enter ();
@@ -66,7 +65,6 @@ Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_nativeCreate
NSA_SET_PTR (env, group, button);
}
}
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), state);
gdk_threads_leave ();
@@ -131,6 +129,21 @@ Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_nativeSetCheckboxGroup
}
JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkToggleButtonSetActive
+ (JNIEnv *env, jobject obj, jboolean is_active)
+{
+ void *ptr;
+
+ ptr = NSA_GET_PTR (env, obj);
+
+ gdk_threads_enter ();
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptr), is_active);
+
+ gdk_threads_leave ();
+}
+
+JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkSetFont
(JNIEnv *env, jobject obj, jstring name, jint style, jint size)
{
@@ -171,26 +184,25 @@ Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkSetFont
}
JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkSetLabel
+Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkButtonSetLabel
(JNIEnv *env, jobject obj, jstring label)
{
- const char *str;
- void *ptr;
+ const char *c_label;
GtkWidget *label_widget;
+ void *ptr;
ptr = NSA_GET_PTR (env, obj);
- label_widget = gtk_bin_get_child (GTK_BIN(ptr));
-
- str = (*env)->GetStringUTFChars (env, label, 0);
+ c_label = (*env)->GetStringUTFChars (env, label, NULL);
gdk_threads_enter ();
- gtk_label_set_label (GTK_LABEL (label_widget), str);
+ label_widget = gtk_bin_get_child (GTK_BIN (ptr));
+ gtk_label_set_text (GTK_LABEL (label_widget), c_label);
gdk_threads_leave ();
- (*env)->ReleaseStringUTFChars (env, label, str);
+ (*env)->ReleaseStringUTFChars (env, label, c_label);
}
static void
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c
index 9b262d33d7d..128443121b2 100644
--- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c
+++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c
@@ -39,38 +39,27 @@ exception statement from your version. */
#include "gtkpeer.h"
#include "gnu_java_awt_peer_gtk_GtkChoicePeer.h"
-static void connect_choice_item_selectable_hook (JNIEnv *env,
- jobject peer_obj,
- GtkItem *menuitem,
- const char *label);
+static void selection_changed (GtkComboBox *combobox, gpointer data);
JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkChoicePeer_create
(JNIEnv *env, jobject obj)
{
GtkWidget *menu;
- GtkOptionMenu *option_menu;
- GtkRequisition child_requisition;
+ GtkComboBox *combobox;
- /* Create global reference and save it for future use */
NSA_SET_GLOBAL_REF (env, obj);
gdk_threads_enter ();
- option_menu = GTK_OPTION_MENU (gtk_option_menu_new ());
- menu = gtk_menu_new ();
- gtk_widget_show (menu);
+ combobox = gtk_combo_box_new_text ();
- gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu);
-
- gtk_widget_size_request (gtk_menu_item_new_with_label (""),
- &child_requisition);
- option_menu->width = child_requisition.width;
- option_menu->height = child_requisition.height;
+ g_signal_connect (combobox, "changed",
+ G_CALLBACK (selection_changed), obj);
gdk_threads_leave ();
- NSA_SET_PTR (env, obj, option_menu);
+ NSA_SET_PTR (env, obj, combobox);
}
JNIEXPORT void JNICALL
@@ -78,45 +67,27 @@ Java_gnu_java_awt_peer_gtk_GtkChoicePeer_append
(JNIEnv *env, jobject obj, jobjectArray items)
{
gpointer ptr;
- GtkMenu *menu;
jsize count, i;
- int need_set_history = 0;
ptr = NSA_GET_PTR (env, obj);
gdk_threads_enter ();
- menu = GTK_MENU (gtk_option_menu_get_menu (GTK_OPTION_MENU (ptr)));
-
- /* Are we adding the first element? */
- if (gtk_option_menu_get_history (GTK_OPTION_MENU (ptr)) < 0)
- need_set_history = 1;
-
count = (*env)->GetArrayLength (env, items);
for (i = 0; i < count; i++)
{
jobject item;
const char *label;
- GtkWidget *menuitem;
item = (*env)->GetObjectArrayElement (env, items, i);
label = (*env)->GetStringUTFChars (env, item, NULL);
- menuitem = gtk_menu_item_new_with_label (label);
- gtk_menu_append (menu, menuitem);
- gtk_widget_show (menuitem);
-
- connect_choice_item_selectable_hook (env, obj,
- GTK_ITEM (menuitem), label);
+ gtk_combo_box_append_text (GTK_COMBO_BOX (ptr), label);
(*env)->ReleaseStringUTFChars (env, item, label);
}
- /* If we just added the first element select it. */
- if (need_set_history)
- gtk_option_menu_set_history (GTK_OPTION_MENU (ptr), 0);
-
gdk_threads_leave ();
}
@@ -126,36 +97,13 @@ Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeAdd
{
void *ptr;
const char *label;
- GtkWidget *menu, *menuitem;
- int current;
- int need_set_history = 0;
ptr = NSA_GET_PTR (env, obj);
label = (*env)->GetStringUTFChars (env, item, 0);
gdk_threads_enter ();
-
- current = gtk_option_menu_get_history (GTK_OPTION_MENU (ptr));
-
- /* Are we adding the first element or below or at the currently
- selected one? */
- if ((current < 0) || (current >= index))
- need_set_history = 1;
-
- menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (ptr));
- menuitem = gtk_menu_item_new_with_label (label);
- gtk_menu_insert (GTK_MENU (menu), menuitem, index);
- gtk_widget_show (menuitem);
-
- connect_choice_item_selectable_hook (env, obj, GTK_ITEM (menuitem), label);
-
- /* If we just added the first element select it.
- If we added at of below the currently selected position make
- the first item the selected one. */
- if (need_set_history)
- gtk_option_menu_set_history (GTK_OPTION_MENU (ptr), 0);
-
+ gtk_combo_box_insert_text (GTK_COMBO_BOX (ptr), index, label);
gdk_threads_leave ();
(*env)->ReleaseStringUTFChars (env, item, label);
@@ -166,50 +114,35 @@ Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeRemove
(JNIEnv *env, jobject obj, jint index)
{
void *ptr;
- GtkContainer *menu;
- GtkWidget *menuitem;
- GList *children;
- int need_set_history = 0;
- int i, from, to;
ptr = NSA_GET_PTR (env, obj);
gdk_threads_enter ();
+ gtk_combo_box_remove_text (GTK_COMBO_BOX (ptr), index);
+ gdk_threads_leave ();
+}
- menu = GTK_CONTAINER (gtk_option_menu_get_menu (GTK_OPTION_MENU (ptr)));
- children = gtk_container_children (menu);
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeRemoveAll
+ (JNIEnv *env, jobject obj)
+{
+ void *ptr;
+ GtkTreeModel *model;
+ gint count, i;
- if (index == -1)
- {
- /* Remove all elements (removeAll) */
- from = g_list_length (children) - 1;
- to = 0;
+ ptr = NSA_GET_PTR (env, obj);
- /* Select the first item to prevent spurious activate signals */
- gtk_option_menu_set_history (GTK_OPTION_MENU (ptr), 0);
- }
- else
- {
- /* Remove the specific index element */
- from = index;
- to = index;
+ gdk_threads_enter ();
- /* Are we removing the currently selected element? */
- if (gtk_option_menu_get_history (GTK_OPTION_MENU (ptr)) == index)
- need_set_history = 1;
- }
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (ptr));
+ count = gtk_tree_model_iter_n_children (model, NULL);
- for (i = from; i >= to; i--)
- {
- menuitem = GTK_WIDGET (g_list_nth (children, i)->data);
- gtk_container_remove (menu, menuitem);
- gtk_widget_destroy (menuitem);
- }
+ /* First, unselect everything, to avoid problems when removing items. */
+ gtk_combo_box_set_active (GTK_COMBO_BOX (ptr), -1);
- /* If we just removed the currently selected element and there are
- still elements left in the list, make the first item the selected one. */
- if (need_set_history && gtk_container_children (menu))
- gtk_option_menu_set_history (GTK_OPTION_MENU (ptr), 0);
+ for (i = count - 1; i >= 0; i--) {
+ gtk_combo_box_remove_text (GTK_COMBO_BOX (ptr), i);
+ }
gdk_threads_leave ();
}
@@ -223,12 +156,12 @@ Java_gnu_java_awt_peer_gtk_GtkChoicePeer_select
ptr = NSA_GET_PTR (env, obj);
gdk_threads_enter ();
- gtk_option_menu_set_history (GTK_OPTION_MENU (ptr), index);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (ptr), index);
gdk_threads_leave ();
}
JNIEXPORT jint JNICALL
-Java_gnu_java_awt_peer_gtk_GtkChoicePeer_getHistory
+Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeGetSelected
(JNIEnv *env, jobject obj)
{
void *ptr;
@@ -237,58 +170,38 @@ Java_gnu_java_awt_peer_gtk_GtkChoicePeer_getHistory
ptr = NSA_GET_PTR (env, obj);
gdk_threads_enter ();
-
- index = gtk_option_menu_get_history (GTK_OPTION_MENU (ptr));
-
+ index = gtk_combo_box_get_active (GTK_COMBO_BOX (ptr));
gdk_threads_leave ();
return index;
}
-static void
-item_activate (GtkItem *item __attribute__((unused)),
- struct item_event_hook_info *ie)
+void selection_changed (GtkComboBox *combobox, jobject peer)
{
jstring label;
- gdk_threads_leave ();
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GValue value;
+ gchar *selected;
+ gint index;
- label = (*gdk_env)->NewStringUTF (gdk_env, ie->label);
- (*gdk_env)->CallVoidMethod (gdk_env, ie->peer_obj,
- choicePostItemEventID,
- label,
- (jint) AWT_ITEM_SELECTED);
- gdk_threads_enter ();
-}
+ index = gtk_combo_box_get_active(combobox);
-static void
-item_removed (gpointer data,
- GClosure gc __attribute__((unused)))
-{
- struct item_event_hook_info *ie = data;
-
- free ((void *) ie->label);
- free (ie);
-}
-
-static void
-connect_choice_item_selectable_hook (JNIEnv *env,
- jobject peer_obj,
- GtkItem *menuitem,
- const char *label)
-{
- struct item_event_hook_info *ie;
- jobject *peer_objGlobPtr;
+ if (index >= 0)
+ {
+ model = gtk_combo_box_get_model (combobox);
- ie = (struct item_event_hook_info *)
- malloc (sizeof (struct item_event_hook_info));
+ gtk_combo_box_get_active_iter (combobox, &iter);
- peer_objGlobPtr = NSA_GET_GLOBAL_REF (env, peer_obj);
- g_assert (peer_objGlobPtr);
+ gtk_tree_model_get (model, &iter, 0, &selected, -1);
- ie->peer_obj = *peer_objGlobPtr;
- ie->label = strdup (label);
+ gdk_threads_leave ();
- g_signal_connect_data (G_OBJECT (menuitem), "activate",
- GTK_SIGNAL_FUNC (item_activate), ie,
- (GClosureNotify) item_removed, 0);
+ label = (*gdk_env)->NewStringUTF (gdk_env, selected);
+ (*gdk_env)->CallVoidMethod (gdk_env, peer,
+ choicePostItemEventID,
+ label,
+ (jint) AWT_ITEM_SELECTED);
+ gdk_threads_enter ();
+ }
}
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c
index 6bc24872dfa..8aaf0d26282 100644
--- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c
+++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c
@@ -473,6 +473,63 @@ Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetCursor
}
JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetParent
+ (JNIEnv *env, jobject obj, jobject parent)
+{
+ void *ptr;
+ void *parent_ptr;
+ GtkWidget *widget;
+ GtkWidget *parent_widget;
+
+ ptr = NSA_GET_PTR (env, obj);
+ parent_ptr = NSA_GET_PTR (env, parent);
+
+ gdk_threads_enter ();
+
+ widget = GTK_WIDGET (ptr);
+ parent_widget = GTK_WIDGET (parent_ptr);
+
+ if (GTK_IS_WINDOW (parent_widget))
+ {
+ GList *children = gtk_container_children
+ (GTK_CONTAINER (GTK_BIN (parent_widget)->child));
+
+ if (GTK_IS_MENU_BAR (children->data))
+ gtk_layout_put (GTK_LAYOUT (children->next->data), widget, 0, 0);
+ else
+ gtk_layout_put (GTK_LAYOUT (children->data), widget, 0, 0);
+ }
+ else
+ if (GTK_IS_SCROLLED_WINDOW (parent_widget))
+ {
+ gtk_scrolled_window_add_with_viewport
+ (GTK_SCROLLED_WINDOW (parent_widget), widget);
+ gtk_viewport_set_shadow_type (GTK_VIEWPORT (widget->parent),
+ GTK_SHADOW_NONE);
+
+ }
+ else
+ gtk_layout_put (GTK_LAYOUT (parent_widget), widget, 0, 0);
+
+ gdk_threads_leave ();
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetSensitive
+ (JNIEnv *env, jobject obj, jboolean sensitive)
+{
+ void *ptr;
+
+ ptr = NSA_GET_PTR (env, obj);
+
+ gdk_threads_enter ();
+
+ gtk_widget_set_sensitive (GTK_WIDGET (ptr), sensitive);
+
+ gdk_threads_leave ();
+}
+
+JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetRequestFocus
(JNIEnv *env, jobject obj)
{
@@ -525,11 +582,11 @@ Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetDispatchKeyEvent
event->key.send_event = 0;
event->key.time = (guint32) when;
- if (mods & AWT_SHIFT_MASK)
+ if (mods & AWT_SHIFT_DOWN_MASK)
event->key.state |= GDK_SHIFT_MASK;
- if (mods & AWT_CTRL_MASK)
+ if (mods & AWT_CTRL_DOWN_MASK)
event->key.state |= GDK_CONTROL_MASK;
- if (mods & AWT_ALT_MASK)
+ if (mods & AWT_ALT_DOWN_MASK)
event->key.state |= GDK_MOD1_MASK;
/* This hack is needed because the AWT has no notion of num lock.
@@ -680,19 +737,33 @@ Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetGetPreferredDimensions
gdk_threads_enter ();
- /* Save the widget's current size request. */
- gtk_widget_size_request (GTK_WIDGET (ptr), &current_req);
+ /* Widgets that extend GtkWindow such as GtkFileChooserDialog may have
+ a default size. These values seem more useful then the natural
+ requisition values, particularly for GtkFileChooserDialog. */
+ if (GTK_IS_WINDOW (ptr))
+ {
+ gint width, height;
+ gtk_window_get_default_size (GTK_WINDOW (ptr), &width, &height);
- /* Get the widget's "natural" size request. */
- gtk_widget_set_size_request (GTK_WIDGET (ptr), -1, -1);
- gtk_widget_size_request (GTK_WIDGET (ptr), &natural_req);
+ dims[0] = width;
+ dims[1] = height;
+ }
+ else
+ {
+ /* Save the widget's current size request. */
+ gtk_widget_size_request (GTK_WIDGET (ptr), &current_req);
+
+ /* Get the widget's "natural" size request. */
+ gtk_widget_set_size_request (GTK_WIDGET (ptr), -1, -1);
+ gtk_widget_size_request (GTK_WIDGET (ptr), &natural_req);
- /* Reset the widget's size request. */
- gtk_widget_set_size_request (GTK_WIDGET (ptr),
- current_req.width, current_req.height);
+ /* Reset the widget's size request. */
+ gtk_widget_set_size_request (GTK_WIDGET (ptr),
+ current_req.width, current_req.height);
- dims[0] = natural_req.width;
- dims[1] = natural_req.height;
+ dims[0] = natural_req.width;
+ dims[1] = natural_req.height;
+ }
gdk_threads_leave ();
@@ -911,45 +982,6 @@ find_gtk_layout (GtkWidget *parent)
return NULL;
}
-#define WIDGET_CLASS(w) GTK_WIDGET_CLASS (GTK_OBJECT (w)->klass)
-
-void
-set_parent (GtkWidget *widget, GtkContainer *parent)
-{
- if (GTK_IS_WINDOW (parent))
- {
- GList *children = gtk_container_children
- (GTK_CONTAINER (GTK_BIN (parent)->child));
-
- if (GTK_IS_MENU_BAR (children->data))
- gtk_layout_put (GTK_LAYOUT (children->next->data), widget, 0, 0);
- else /* GTK_IS_LAYOUT (children->data) */
- gtk_layout_put (GTK_LAYOUT (children->data), widget, 0, 0);
- }
- else
- if (GTK_IS_SCROLLED_WINDOW (parent))
- {
-/* if (WIDGET_CLASS (widget)->set_scroll_adjustments_signal) */
-/* gtk_container_add (GTK_CONTAINER (parent), widget); */
-/* else */
-/* { */
- gtk_scrolled_window_add_with_viewport
- (GTK_SCROLLED_WINDOW (parent), widget);
- gtk_viewport_set_shadow_type (GTK_VIEWPORT (widget->parent),
- GTK_SHADOW_NONE);
-/* } */
-
- }
-/* gtk_layout_put */
-/* (GTK_LAYOUT (GTK_BIN (parent)->child), widget, 0, 0); */
-
-/* if (GTK_IS_SCROLLED_WINDOW (parent)) */
-/* gtk_layout_put */
-/* (GTK_LAYOUT (GTK_BIN (GTK_BIN (parent)->child)->child), widget, 0, 0); */
- else
- gtk_layout_put (GTK_LAYOUT (parent), widget, 0, 0);
-}
-
JNIEXPORT jboolean JNICALL
Java_gnu_java_awt_peer_gtk_GtkComponentPeer_isEnabled
(JNIEnv *env, jobject obj)
@@ -981,105 +1013,6 @@ Java_gnu_java_awt_peer_gtk_GtkComponentPeer_modalHasGrab
return retval;
}
-JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GtkComponentPeer_set__Ljava_lang_String_2Ljava_lang_String_2
- (JNIEnv *env, jobject obj, jstring jname, jstring jvalue)
-{
- const char *name;
- const char *value;
- void *ptr;
-
- ptr = NSA_GET_PTR (env, obj);
- name = (*env)->GetStringUTFChars (env, jname, NULL);
- value = (*env)->GetStringUTFChars (env, jvalue, NULL);
-
- gdk_threads_enter();
- g_object_set(ptr, name, value, NULL);
- gdk_threads_leave();
-
- (*env)->ReleaseStringUTFChars (env, jname, name);
- (*env)->ReleaseStringUTFChars (env, jvalue, value);
-}
-
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_set__Ljava_lang_String_2Z
- (JNIEnv *env, jobject obj, jstring jname, jboolean value)
-{
- const char *name;
- void *ptr;
-
- ptr = NSA_GET_PTR (env, obj);
-
- name = (*env)->GetStringUTFChars (env, jname, NULL);
-
- gdk_threads_enter();
- g_object_set(ptr, name, value, NULL);
- gdk_threads_leave();
-
- (*env)->ReleaseStringUTFChars (env, jname, name);
-}
-
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_set__Ljava_lang_String_2I
- (JNIEnv *env, jobject obj, jstring jname, jint value)
-{
- const char *name;
- void *ptr;
-
- ptr = NSA_GET_PTR (env, obj);
- name = (*env)->GetStringUTFChars (env, jname, NULL);
-
- gdk_threads_enter();
- g_object_set(ptr, name, value, NULL);
- gdk_threads_leave();
-
- (*env)->ReleaseStringUTFChars (env, jname, name);
-}
-
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_set__Ljava_lang_String_2F
- (JNIEnv *env, jobject obj, jstring jname, jfloat value)
-{
- const char *name;
- void *ptr;
-
- ptr = NSA_GET_PTR (env, obj);
- name = (*env)->GetStringUTFChars (env, jname, NULL);
-
- gdk_threads_enter();
- g_object_set(ptr, name, value, NULL);
- gdk_threads_leave();
-
- (*env)->ReleaseStringUTFChars (env, jname, name);
-}
-
-JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GtkComponentPeer_set__Ljava_lang_String_2Ljava_lang_Object_2
- (JNIEnv *env, jobject obj1, jstring jname, jobject obj2)
-{
- const char *name;
- void *ptr1, *ptr2;
-
- ptr1 = NSA_GET_PTR (env, obj1);
- ptr2 = NSA_GET_PTR (env, obj2);
-
- name = (*env)->GetStringUTFChars (env, jname, NULL);
-
- /* special case to catch where we need to set the parent */
- if (!strcmp (name, "parent"))
- {
- gdk_threads_enter ();
- set_parent (GTK_WIDGET (ptr1), GTK_CONTAINER (ptr2));
- gdk_threads_leave ();
-
- (*env)->ReleaseStringUTFChars (env, jname, name);
- return;
- }
-
- gdk_threads_enter();
- g_object_set(ptr1, name, ptr2, NULL);
- gdk_threads_leave();
-
- (*env)->ReleaseStringUTFChars (env, jname, name);
-}
-
static gboolean
filter_expose_event_handler (GtkWidget *widget, GdkEvent *event, jobject peer)
{
@@ -1111,6 +1044,7 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_addExposeFilt
GList *children;
void *ptr = NSA_GET_PTR (env, obj);
jobject *gref = NSA_GET_GLOBAL_REF (env, obj);
+ gulong hid;
g_assert (gref);
@@ -1144,10 +1078,9 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_addExposeFilt
{
filterobj = GTK_OBJECT(ptr);
}
-
- gulong hid = g_signal_handler_find(filterobj,
- G_SIGNAL_MATCH_FUNC,
- 0, 0, NULL, *pre_event_handler, NULL);
+ hid = g_signal_handler_find(filterobj,
+ G_SIGNAL_MATCH_FUNC,
+ 0, 0, NULL, *pre_event_handler, NULL);
if (hid > 0)
{
g_signal_handler_block(filterobj, hid);
@@ -1166,6 +1099,7 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_removeExposeF
GList *children;
void *ptr = NSA_GET_PTR (env, obj);
jobject *gref = NSA_GET_GLOBAL_REF (env, obj);
+ gulong hid;
g_assert (gref);
@@ -1202,9 +1136,9 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_removeExposeF
g_signal_handlers_disconnect_by_func (filterobj,
*filter_expose_event_handler, *gref);
- gulong hid = g_signal_handler_find(filterobj,
- G_SIGNAL_MATCH_FUNC,
- 0, 0, NULL, *pre_event_handler, NULL);
+ hid = g_signal_handler_find(filterobj,
+ G_SIGNAL_MATCH_FUNC,
+ 0, 0, NULL, *pre_event_handler, NULL);
if (hid > 0)
{
g_signal_handler_unblock(filterobj, hid);
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c
index 8fb619e2563..7cf405df902 100644
--- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c
+++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c
@@ -58,11 +58,11 @@ button_to_awt_mods (int button)
switch (button)
{
case 1:
- return AWT_BUTTON1_MASK;
+ return AWT_BUTTON1_DOWN_MASK;
case 2:
- return AWT_BUTTON2_MASK;
+ return AWT_BUTTON2_DOWN_MASK;
case 3:
- return AWT_BUTTON3_MASK;
+ return AWT_BUTTON3_DOWN_MASK;
}
return 0;
@@ -74,11 +74,11 @@ state_to_awt_mods (guint state)
jint result = 0;
if (state & GDK_SHIFT_MASK)
- result |= AWT_SHIFT_MASK;
+ result |= AWT_SHIFT_DOWN_MASK;
if (state & GDK_CONTROL_MASK)
- result |= AWT_CTRL_MASK;
+ result |= AWT_CTRL_DOWN_MASK;
if (state & GDK_MOD1_MASK)
- result |= AWT_ALT_MASK;
+ result |= AWT_ALT_DOWN_MASK;
return result;
}
@@ -89,17 +89,17 @@ state_to_awt_mods_with_button_states (guint state)
jint result = 0;
if (state & GDK_SHIFT_MASK)
- result |= AWT_SHIFT_MASK;
+ result |= AWT_SHIFT_DOWN_MASK;
if (state & GDK_CONTROL_MASK)
- result |= AWT_CTRL_MASK;
+ result |= AWT_CTRL_DOWN_MASK;
if (state & GDK_MOD1_MASK)
- result |= AWT_ALT_MASK;
+ result |= AWT_ALT_DOWN_MASK;
if (state & GDK_BUTTON1_MASK)
- result |= AWT_BUTTON1_MASK;
+ result |= AWT_BUTTON1_DOWN_MASK;
if (state & GDK_BUTTON2_MASK)
- result |= AWT_BUTTON2_MASK;
+ result |= AWT_BUTTON2_DOWN_MASK;
if (state & GDK_BUTTON3_MASK)
- result |= AWT_BUTTON3_MASK;
+ result |= AWT_BUTTON3_DOWN_MASK;
return result;
}
@@ -124,29 +124,29 @@ keyevent_state_to_awt_mods (GdkEvent *event)
if (event->key.keyval == GDK_Shift_L
|| event->key.keyval == GDK_Shift_R)
- result |= AWT_SHIFT_MASK;
+ result |= AWT_SHIFT_DOWN_MASK;
else
{
if (state & GDK_SHIFT_MASK)
- result |= AWT_SHIFT_MASK;
+ result |= AWT_SHIFT_DOWN_MASK;
}
if (event->key.keyval == GDK_Control_L
|| event->key.keyval == GDK_Control_R)
- result |= AWT_CTRL_MASK;
+ result |= AWT_CTRL_DOWN_MASK;
else
{
if (state & GDK_CONTROL_MASK)
- result |= AWT_CTRL_MASK;
+ result |= AWT_CTRL_DOWN_MASK;
}
if (event->key.keyval == GDK_Alt_L
|| event->key.keyval == GDK_Alt_R)
- result |= AWT_ALT_MASK;
+ result |= AWT_ALT_DOWN_MASK;
else
{
if (state & GDK_MOD1_MASK)
- result |= AWT_ALT_MASK;
+ result |= AWT_ALT_DOWN_MASK;
}
}
else if (event->type == GDK_KEY_RELEASE)
@@ -157,20 +157,20 @@ keyevent_state_to_awt_mods (GdkEvent *event)
&& event->key.keyval != GDK_Shift_R)
{
if (state & GDK_SHIFT_MASK)
- result |= AWT_SHIFT_MASK;
+ result |= AWT_SHIFT_DOWN_MASK;
}
if (event->key.keyval != GDK_Control_L
&& event->key.keyval != GDK_Control_R)
{
if (state & GDK_CONTROL_MASK)
- result |= AWT_CTRL_MASK;
+ result |= AWT_CTRL_DOWN_MASK;
}
if (event->key.keyval != GDK_Alt_L
&& event->key.keyval != GDK_Alt_R)
{
if (state & GDK_MOD1_MASK)
- result |= AWT_ALT_MASK;
+ result |= AWT_ALT_DOWN_MASK;
}
}
@@ -885,8 +885,8 @@ pre_event_handler (GtkWidget *widget, GdkEvent *event, jobject peer)
postMouseEventID,
AWT_MOUSE_PRESSED,
(jlong)event->button.time,
- state_to_awt_mods (event->button.state) |
- button_to_awt_mods (event->button.button),
+ state_to_awt_mods (event->button.state)
+ | button_to_awt_mods (event->button.button),
(jint)event->button.x,
(jint)event->button.y,
click_count,
@@ -902,8 +902,8 @@ pre_event_handler (GtkWidget *widget, GdkEvent *event, jobject peer)
postMouseEventID,
AWT_MOUSE_RELEASED,
(jlong)event->button.time,
- state_to_awt_mods (event->button.state) |
- button_to_awt_mods (event->button.button),
+ state_to_awt_mods (event->button.state)
+ | button_to_awt_mods (event->button.button),
(jint)event->button.x,
(jint)event->button.y,
click_count,
@@ -923,8 +923,8 @@ pre_event_handler (GtkWidget *widget, GdkEvent *event, jobject peer)
postMouseEventID,
AWT_MOUSE_CLICKED,
(jlong)event->button.time,
- state_to_awt_mods (event->button.state) |
- button_to_awt_mods (event->button.button),
+ state_to_awt_mods (event->button.state)
+ | button_to_awt_mods (event->button.button),
(jint)event->button.x,
(jint)event->button.y,
click_count,
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFileDialogPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFileDialogPeer.c
index 95bec4a10be..594fcce4165 100644
--- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFileDialogPeer.c
+++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFileDialogPeer.c
@@ -151,6 +151,7 @@ gboolean filenameFilterCallback (const GtkFileFilterInfo *filter_info,
jclass cx;
jmethodID id;
jstring *filename;
+ gboolean accepted;
cx = (*gdk_env)->GetObjectClass (gdk_env, (jobject) obj);
id = (*gdk_env)->GetMethodID (gdk_env, cx, "filenameFilterCallback",
@@ -159,7 +160,7 @@ gboolean filenameFilterCallback (const GtkFileFilterInfo *filter_info,
filename = (*gdk_env)->NewStringUTF(gdk_env, filter_info->filename);
gdk_threads_leave();
- gboolean accepted = (*gdk_env)->CallBooleanMethod(gdk_env, obj, id, filename);
+ accepted = (*gdk_env)->CallBooleanMethod(gdk_env, obj, id, filename);
gdk_threads_enter();
return accepted;
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c
index a9da539f223..99107a1282c 100644
--- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c
+++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c
@@ -63,12 +63,10 @@ jmethodID postWindowEventID;
JNIEnv *gdk_env;
-#ifdef PORTABLE_NATIVE_SYNC
-JavaVM *gdk_vm;
-#endif
-
GtkWindowGroup *global_gtk_window_group;
+static void init_glib_threads(JNIEnv *, jint);
+
double dpi_conversion_factor;
static void init_dpi_conversion_factor ();
@@ -78,10 +76,17 @@ static void dpi_changed_cb (GtkSettings *settings,
/*
* Call gtk_init. It is very important that this happen before any other
* gtk calls.
+ *
+ * The portableNativeSync argument may have the values:
+ * 1 if the Java property gnu.classpath.awt.gtk.portable.native.sync
+ * is set to "true".
+ * 0 if it is set to "false"
+ * -1 if unset.
*/
JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GtkMainThread_gtkInit (JNIEnv *env, jclass clazz)
+Java_gnu_java_awt_peer_gtk_GtkMainThread_gtkInit (JNIEnv *env, jclass clazz,
+ jint portableNativeSync)
{
int argc = 1;
char **argv;
@@ -91,23 +96,22 @@ Java_gnu_java_awt_peer_gtk_GtkMainThread_gtkInit (JNIEnv *env, jclass clazz)
gtkmenuitempeer, gtktextcomponentpeer, window;
NSA_INIT (env, clazz);
+ gdk_env = env;
/* GTK requires a program's argc and argv variables, and requires that they
- be valid. */
-
- argv = (char **) malloc (sizeof (char *) * 2);
- argv[0] = "";
+ be valid. Set it up. */
+ argv = (char **) g_malloc (sizeof (char *) * 2);
+ argv[0] = (char *) g_malloc(1);
+#if 1
+ strcpy(argv[0], "");
+#else /* The following is a more efficient alternative, but less intuitively
+ * expresses what we are trying to do. This code is only run once, so
+ * I'm going for intuitive. */
+ argv[0][0] = '\0';
+#endif
argv[1] = NULL;
- /* until we have JDK 1.2 JNI, assume we have a VM with threads that
- match what GLIB was compiled for */
-#ifdef PORTABLE_NATIVE_SYNC
- (*env)->GetJavaVM( env, &gdk_vm );
- g_thread_init ( &g_thread_jni_functions );
- printf("called gthread init\n");
-#else
- g_thread_init ( NULL );
-#endif
+ init_glib_threads(env, portableNativeSync);
/* From GDK 2.0 onwards we have to explicitly call gdk_threads_init */
gdk_threads_init();
@@ -122,21 +126,19 @@ Java_gnu_java_awt_peer_gtk_GtkMainThread_gtkInit (JNIEnv *env, jclass clazz)
we're shutting down. */
atexit (gdk_threads_enter);
- gdk_env = env;
gdk_event_handler_set ((GdkEventFunc)awt_event_handler, NULL, NULL);
if ((homedir = getenv ("HOME")))
{
- rcpath = (char *) malloc (strlen (homedir) + strlen (RC_FILE) + 2);
+ rcpath = (char *) g_malloc (strlen (homedir) + strlen (RC_FILE) + 2);
sprintf (rcpath, "%s/%s", homedir, RC_FILE);
}
gtk_rc_parse ((rcpath) ? rcpath : RC_FILE);
- if (rcpath)
- free (rcpath);
-
- free (argv);
+ g_free (rcpath);
+ g_free (argv[0]);
+ g_free (argv);
/* setup cached IDs for posting GTK events to Java */
/* gtkgenericpeer = (*env)->FindClass (env, */
@@ -204,6 +206,37 @@ Java_gnu_java_awt_peer_gtk_GtkMainThread_gtkInit (JNIEnv *env, jclass clazz)
init_dpi_conversion_factor ();
}
+
+/** Initialize GLIB's threads properly, based on the value of the
+ gnu.classpath.awt.gtk.portable.native.sync Java system property. If
+ that's unset, use the PORTABLE_NATIVE_SYNC config.h macro. (TODO:
+ In some release following 0.10, that config.h macro will go away.)
+ */
+static void
+init_glib_threads(JNIEnv *env, jint portableNativeSync)
+{
+ if (portableNativeSync < 0)
+ {
+#ifdef PORTABLE_NATIVE_SYNC /* Default value, if not set by the Java system
+ property */
+ portableNativeSync = 1;
+#else
+ portableNativeSync = 0;
+#endif
+ }
+
+ (*env)->GetJavaVM( env, &the_vm );
+ if (portableNativeSync)
+ g_thread_init ( &portable_native_sync_jni_functions );
+ else
+ g_thread_init ( NULL );
+
+ /* Debugging progress message; uncomment if needed: */
+ /* printf("called gthread init\n"); */
+}
+
+
+
/*
* Run gtk_main and block.
*/
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuBarPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuBarPeer.c
index 8034f647300..53c7351e6ec 100644
--- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuBarPeer.c
+++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuBarPeer.c
@@ -70,6 +70,29 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkMenuBarPeer_addMenu
gdk_threads_leave ();
}
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkMenuBarPeer_nativeSetHelpMenu
+ (JNIEnv *env, jobject obj, jobject menupeer)
+{
+ static void *helpmenu;
+ void *mbar, *menu;
+ GList *list;
+
+ mbar = NSA_GET_PTR (env, obj);
+ menu = NSA_GET_PTR (env, menupeer);
+
+ gdk_threads_enter ();
+ if (helpmenu != NULL)
+ {
+ list = gtk_container_children (GTK_CONTAINER (mbar));
+ while (list != NULL && list->data != helpmenu)
+ list = list->next;
+ if (list != NULL && list->data == helpmenu)
+ gtk_container_remove (GTK_CONTAINER (mbar), GTK_WIDGET (list->data));
+ }
+ helpmenu = menu;
+ gdk_threads_leave ();
+}
+
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkMenuBarPeer_delMenu
(JNIEnv *env, jobject obj, jint index)
{
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuItemPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuItemPeer.c
index 70fc8095519..5d5de6780a0 100644
--- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuItemPeer.c
+++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuItemPeer.c
@@ -86,6 +86,18 @@ Java_gnu_java_awt_peer_gtk_GtkMenuItemPeer_connectSignals
gdk_threads_leave ();
}
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkMenuItemPeer_setEnabled
+ (JNIEnv *env, jobject obj, jboolean enabled)
+{
+ void *ptr;
+
+ ptr = NSA_GET_PTR (env, obj);
+
+ gdk_threads_enter ();
+ gtk_widget_set_sensitive (GTK_WIDGET (ptr), enabled);
+ gdk_threads_leave ();
+}
+
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkMenuItemPeer_setLabel
(JNIEnv *env, jobject obj, jstring label)
{
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuPeer.c
index 0bb0ec52567..1ffe61b0c52 100644
--- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuPeer.c
+++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuPeer.c
@@ -39,20 +39,6 @@ exception statement from your version. */
#include "gtkpeer.h"
#include "gnu_java_awt_peer_gtk_GtkMenuPeer.h"
-static void
-accel_attach (GtkMenuItem *menu_item,
- gpointer *user_data __attribute__((unused)))
-{
- GtkAccelGroup *accel;
-
- accel = gtk_menu_get_accel_group (GTK_MENU (menu_item->submenu));
- /* FIXME: update this to use GTK-2.4 GtkActions. */
-#if 0
- _gtk_accel_group_attach (accel,
- G_OBJECT (gtk_widget_get_toplevel (GTK_WIDGET(menu_item))));
-#endif
-}
-
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkMenuPeer_setupAccelGroup
(JNIEnv *env, jobject obj, jobject parent)
{
@@ -65,14 +51,6 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkMenuPeer_setupAccelGroup
{
gtk_menu_set_accel_group (GTK_MENU (GTK_MENU_ITEM (ptr1)->submenu),
gtk_accel_group_new ());
-
- if (GTK_WIDGET_REALIZED (GTK_WIDGET (ptr1)))
- accel_attach (GTK_MENU_ITEM (ptr1), NULL);
- else
- g_signal_connect (G_OBJECT (ptr1),
- "realize",
- GTK_SIGNAL_FUNC (accel_attach),
- NULL);
}
else
{
@@ -128,6 +106,24 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkMenuPeer_create
(*env)->ReleaseStringUTFChars (env, label, str);
}
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkMenuPeer_addTearOff
+ (JNIEnv *env, jobject obj)
+{
+ void *ptr1;
+ GtkWidget *menu, *item;
+
+ ptr1 = NSA_GET_PTR (env, obj);
+
+ gdk_threads_enter ();
+
+ menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (ptr1));
+ item = gtk_tearoff_menu_item_new ();
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show (item);
+
+ gdk_threads_leave ();
+}
+
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkMenuPeer_addItem
(JNIEnv *env, jobject obj, jobject menuitempeer, jint key, jboolean shift)
{
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextComponentPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextComponentPeer.c
index 2d62c33a4d7..771f2b81d75 100644
--- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextComponentPeer.c
+++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextComponentPeer.c
@@ -151,7 +151,6 @@ Java_gnu_java_awt_peer_gtk_GtkTextComponentPeer_setCaretPosition
GtkWidget *text = NULL;
GtkTextBuffer *buf;
GtkTextIter iter;
- GtkTextMark *mark;
GtkTextMark *oldmark;
GtkTextIter olditer;
int oldpos;
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextFieldPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextFieldPeer.c
index 5bea49a3f3c..2a6666a0d83 100644
--- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextFieldPeer.c
+++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextFieldPeer.c
@@ -62,6 +62,47 @@ Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_create
NSA_SET_PTR (env, obj, entry);
}
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_gtkWidgetSetBackground
+ (JNIEnv *env, jobject obj, jint red, jint green, jint blue)
+{
+ GdkColor color;
+ void *ptr;
+
+ ptr = NSA_GET_PTR (env, obj);
+
+ color.red = (red / 255.0) * 65535;
+ color.green = (green / 255.0) * 65535;
+ color.blue = (blue / 255.0) * 65535;
+
+ gdk_threads_enter ();
+
+ gtk_widget_modify_base (GTK_WIDGET (ptr), GTK_STATE_NORMAL, &color);
+
+ gdk_threads_leave ();
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_gtkWidgetSetForeground
+ (JNIEnv *env, jobject obj, jint red, jint green, jint blue)
+{
+ GdkColor color;
+ void *ptr;
+
+ ptr = NSA_GET_PTR (env, obj);
+
+ color.red = (red / 255.0) * 65535;
+ color.green = (green / 255.0) * 65535;
+ color.blue = (blue / 255.0) * 65535;
+
+ gdk_threads_enter ();
+
+ gtk_widget_modify_text (GTK_WIDGET (ptr), GTK_STATE_NORMAL, &color);
+ gtk_widget_modify_base (GTK_WIDGET (ptr), GTK_STATE_SELECTED, &color);
+
+ gdk_threads_leave ();
+}
+
JNIEXPORT jint JNICALL
Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_gtkEntryGetBorderWidth
(JNIEnv *env, jobject obj)
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c
index 4d11e6201bc..508893168b1 100644
--- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c
+++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c
@@ -104,7 +104,6 @@ Java_gnu_java_awt_peer_gtk_GtkWindowPeer_create
insets = (*env)->GetIntArrayElements (env, jinsets, 0);
insets[0] = insets[1] = insets[2] = insets[3] = 0;
- /* Create global reference and save it for future use */
NSA_SET_GLOBAL_REF (env, obj);
gdk_threads_enter ();
@@ -163,6 +162,56 @@ Java_gnu_java_awt_peer_gtk_GtkWindowPeer_create
}
JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetTitle
+ (JNIEnv *env, jobject obj, jstring title)
+{
+ const char *c_title;
+ void *ptr;
+
+ ptr = NSA_GET_PTR (env, obj);
+
+ c_title = (*env)->GetStringUTFChars (env, title, NULL);
+
+ gdk_threads_enter ();
+
+ gtk_window_set_title (GTK_WINDOW (ptr), c_title);
+
+ gdk_threads_leave ();
+
+ (*env)->ReleaseStringUTFChars (env, title, c_title);
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetResizable
+ (JNIEnv *env, jobject obj, jboolean resizable)
+{
+ void *ptr;
+
+ ptr = NSA_GET_PTR (env, obj);
+
+ gdk_threads_enter ();
+
+ gtk_window_set_policy (GTK_WINDOW (ptr), resizable, resizable, FALSE);
+
+ gdk_threads_leave ();
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetModal
+ (JNIEnv *env, jobject obj, jboolean modal)
+{
+ void *ptr;
+
+ ptr = NSA_GET_PTR (env, obj);
+
+ gdk_threads_enter ();
+
+ gtk_window_set_modal (GTK_WINDOW (ptr), modal);
+
+ gdk_threads_leave ();
+}
+
+JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetVisible
(JNIEnv *env, jobject obj, jboolean visible)
{
@@ -486,6 +535,72 @@ Java_gnu_java_awt_peer_gtk_GtkFramePeer_gtkLayoutSetVisible
gdk_threads_leave ();
}
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkFramePeer_nativeSetIconImageFromDecoder
+ (JNIEnv *env, jobject obj, jobject decoder)
+{
+ void *ptr;
+ GdkPixbufLoader *loader = NULL;
+ GdkPixbuf *pixbuf = NULL;
+
+ ptr = NSA_GET_PTR (env, obj);
+
+ loader = NSA_GET_PB_PTR (env, decoder);
+ g_assert (loader != NULL);
+
+ gdk_threads_enter ();
+
+ pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+ g_assert (pixbuf != NULL);
+
+ gtk_window_set_icon (GTK_WINDOW (ptr), pixbuf);
+
+ gdk_threads_leave ();
+}
+
+void free_pixbuf_data (guchar *pixels, gpointer data __attribute__((unused)))
+{
+ free(pixels);
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkFramePeer_nativeSetIconImageFromData
+ (JNIEnv *env, jobject obj, jintArray pixelArray, jint width, jint height)
+{
+ void *ptr;
+ GdkPixbuf *pixbuf;
+ jint *pixels;
+ int pixels_length, i;
+ guchar *data;
+
+ ptr = NSA_GET_PTR (env, obj);
+
+ pixels = (*env)->GetIntArrayElements (env, pixelArray, 0);
+ pixels_length = (*env)->GetArrayLength (env, pixelArray);
+
+ data = malloc (sizeof (guchar) * pixels_length);
+ for (i = 0; i < pixels_length; i++)
+ data[i] = (guchar) pixels[i];
+
+ gdk_threads_enter ();
+
+ pixbuf = gdk_pixbuf_new_from_data (data,
+ GDK_COLORSPACE_RGB,
+ TRUE,
+ 8,
+ width,
+ height,
+ width*4,
+ free_pixbuf_data,
+ NULL);
+
+ gtk_window_set_icon (GTK_WINDOW (ptr), pixbuf);
+
+ gdk_threads_leave ();
+
+ (*env)->ReleaseIntArrayElements(env, pixelArray, pixels, 0);
+}
+
static void
window_get_frame_extents (GtkWidget *window,
int *top, int *left, int *bottom, int *right)
diff --git a/libjava/jni/gtk-peer/gthread-jni.c b/libjava/jni/gtk-peer/gthread-jni.c
index 3dd5596b4bc..ee79424475c 100644
--- a/libjava/jni/gtk-peer/gthread-jni.c
+++ b/libjava/jni/gtk-peer/gthread-jni.c
@@ -40,142 +40,1166 @@ exception statement from your version. */
/************************************************************************/
/*
- * Julian Dolby (dolby@us.ibm.com)
- * February 7, 2003
+ * @author Julian Dolby (dolby@us.ibm.com)
+ * @date February 7, 2003 implemented for GLIB v.1
+ *
+ *
+ * @author Steven Augart
+ * <steve+classpath at augart dot com>, <augart at watson dot ibm dot com>
+ * @date April 30, 2004 -- May 10 2004: Support new functions for Glib v.2,
+ * fix cond_wait to free and re-acquire the mutex,
+ * replaced trylock stub implementation with a full one.
*
* This code implements the GThreadFunctions interface for GLIB using
* Java threading primitives. All of the locking and conditional variable
* functionality required by GThreadFunctions is implemented using the
* monitor and wait/notify functionality of Java objects. The thread-
- * local fucntionality uses the java.lang.ThreadLocal class.
+ * local functionality uses the java.lang.ThreadLocal class.
+ *
+ * Classpath's AWT support uses GTK+ peers. GTK+ uses GLIB. GLIB by default
+ * uses the platform's native threading model -- pthreads in most cases. If
+ * the Java runtime doesn't use the native threading model, then it needs this
+ * code in order to use Classpath's (GTK+-based) AWT routines.
*
- * This code is designed to be portable in that it makes no assumptions
+ * This code should be portable; I believe it makes no assumptions
* about the underlying VM beyond that it implements the JNI functionality
* that this code uses.
*
- * The one piece that does not really work is trylock for mutexes. The
- * Java locking model does not include such functionality, and I do not
- * see how to implement it without knowing something about how the VM
- * implements locking.
+ * Currently, use of this code is governed by the configuration option
+ * --enable-portable-native-sync. We will soon add a VM hook so the VM can
+ * select which threading model it wants to use at run time; at that point,
+ * the configuration option will go away.
+ *
+ * The code in this file uses only JNI 1.1, except for one JNI 1.2 function:
+ * GetEnv, in the JNI Invocation API. (There seems to be no way around using
+ * GetEnv).
+ *
+ * ACKNOWLEDGEMENT:
+ *
+ * I would like to thank Mark Wielaard for his kindness in spending at least
+ * six hours of his own time in reviewing this code and correcting my GNU
+ * coding and commenting style. --Steve Augart
+ *
*
* NOTES:
*
- * I have tested it only on JikesRVM---the CVS head as of early February
- * 2003.
+ * This code has been tested with Jikes RVM and with Kaffe.
*
- * Currently, use of this code is governed by the configuration option
- * --enable-portable-native-sync
+ * This code should have proper automated unit tests. I manually tested it
+ * by running an application that uses AWT. --Steven Augart
+ *
+ * MINOR NIT:
*
+ * - Using a jboolean in the arglist to "throw()" and "rethrow()"
+ * triggers many warnings from GCC's -Wconversion operation, because that
+ * is not the same as the conversion (upcast to an int) that would occur in
+ * the absence of a prototype.
+ *
+ * It would be very slightly more efficient to just pass the jboolean, but
+ * is not worth the clutter of messages. The right solution would be to
+ * turn off the -Wconversion warning for just this file, *except* that
+ * -Wconversion also warns you against constructs such as:
+ * unsigned u = -1;
+ * and that is a useful warning. So I went from a "jboolean" to a
+ * "gboolean" (-Wconversion is not enabled by default for GNU Classpath,
+ * but it is in my own CFLAGS, which, for gcc 3.3.3, read: -pipe -ggdb3 -W
+ * -Wall -Wbad-function-cast -Wcast-align -Wpointer-arith -Wcast-qual
+ * -Wshadow -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations
+ * -fkeep-static-consts -fkeep-inline-functions -Wundef -Wwrite-strings
+ * -Wno-aggregate-return -Wmissing-noreturn -Wnested-externs -Wtrigraphs
+ * -Wconversion -Wsign-compare -Wno-float-equal -Wmissing-format-attribute
+ * -Wno-unreachable-code -Wdisabled-optimization )
*/
+#include <config.h>
+
+/************************************************************************/
+/* Configuration */
+/************************************************************************/
+
+/** Tracing and Reporting **/
+#define TRACE_API_CALLS 0 /* announce entry and exit into each method,
+ by printing to stderr. */
+
+#define TRACE_MONITORS 0 /* Every enterMonitor() and exitMonitor() goes
+ to stderr. */
+
+/** Trouble handling. There is a discussion below of this. **/
+#define EXPLAIN_TROUBLE 1 /* Describe any unexpected trouble that
+ happens. This is a superset
+ of EXPLAIN_BROKEN, and if set trumps an
+ unset EXPLAIN_BROKEN. It is not a strict
+ superset, since at the moment there is no
+ TROUBLE that is not also BROKEN.
+
+ Use criticalMsg() to describe the problem.
+ */
+
+#define EXPLAIN_BROKEN 1 /* Describe trouble that is serious enough to
+ be BROKEN. (Right now all trouble is at
+ least BROKEN.) */
+
+/* There is no EXPLAIN_BADLY_BROKEN definition. We always explain
+ BADLY_BROKEN trouble, since there is no other way to report it. */
+
+
+/** Error Handling **/
+#define DIE_IF_BROKEN 1 /* Dies if serious trouble happens. There is
+ really no non-serious trouble, except
+ possibly problems that arise during
+ pthread_create, which are reported by a
+ GError.
+
+ If you do not set DIE_IF_BROKEN, then
+ trouble will raise a Java RuntimeException.
+ We probably do want to die right away,
+ since anything that's BROKEN really
+ indicates a programming error or a
+ system-wide error, and that's what the glib
+ documentation says you should do in case of
+ that kind of error in a glib-style
+ function. But it does work to turn this
+ off. */
+
+#if DIE_IF_BROKEN
+#define DIE_IF_BADLY_BROKEN 1 /* DIE_IF_BROKEN implies DIE_IF_BADLY_BROKEN */
+#else
+#define DIE_IF_BADLY_BROKEN 1 /* Die if the system is badly broken --
+ that is, if we have further trouble while
+ attempting to throw an exception
+ upwards, or if we are unable to generate
+ one of the classes we'll need in order to
+ throw wrapped exceptions upward.
+
+ If unset, we will print a warning message,
+ and limp along anyway. Not that the system
+ is likely to work. */
+#endif
+
+/** Performance tuning parameters **/
+
+#define ENABLE_EXPENSIVE_ASSERTIONS 0 /* Enable expensive assertions? */
+
+#define DELETE_LOCAL_REFS 1 /* Whether to delete local references.
+
+ JNI only guarantees that there wil be 16
+ available. (Jikes RVM provides an number
+ only limited by VM memory.)
+
+ Jikes RVM will probably perform faster if
+ this is turned off, but other VMs may need
+ this to be turned on in order to perform at
+ all, or might need it if things change.
+
+ Remember, we don't know how many of those
+ local refs might have already been used up
+ by higher layers of JNI code that end up
+ calling g_thread_self(),
+ g_thread_set_private(), and so on.
+
+ We set this to 1 for GNU Classpath, since
+ one of our principles is "always go for the
+ most robust implementation" */
+
+#define HAVE_JNI_VERSION_1_2 0 /* Assume we don't. We could
+ dynamically check for this. We will
+ assume JNI 1.2 in later versions of
+ Classpath.
+
+ As it stands, the code in this file
+ already needs one JNI 1.2 function:
+ GetEnv, in the JNI Invocation API.
+
+ TODO This code hasn't been tested yet.
+ And really hasn't been implemented yet.
+ */
/************************************************************************/
/* Global data */
/************************************************************************/
+#if defined HAVE_STDINT_H
+#include <stdint.h> /* provides intptr_t */
+#elif defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#include <stdio.h> /* snprintf */
+#include <stdarg.h> /* va_list */
#include "gthread-jni.h"
+#include <assert.h> /* assert() */
+
+/* For Java thread priority constants. */
+#include <gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.h>
+
+/* Since not all JNI header generators actually define constants we
+ define them here explicitly. */
+#ifndef gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_MIN_PRIORITY
+#define gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_MIN_PRIORITY 1
+#endif
+#ifndef gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_NORM_PRIORITY
+#define gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_NORM_PRIORITY 5
+#endif
+#ifndef gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_MAX_PRIORITY
+#define gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_MAX_PRIORITY 10
+#endif
+
+/* The VM handle. This is set in
+ Java_gnu_java_awt_peer_gtk_GtkMainThread_gtkInit */
+JavaVM *the_vm;
+
+/* Unions used for type punning. */
+union env_union
+{
+ void **void_env;
+ JNIEnv **jni_env;
+};
+
+union func_union
+{
+ void *void_func;
+ GThreadFunc g_func;
+};
+
+/* Forward Declarations for Functions */
+static int threadObj_set_priority (JNIEnv * env, jobject threadObj,
+ GThreadPriority gpriority);
+static void fatalMsg (const char fmt[], ...)
+ __attribute__ ((format (printf, 1, 2)))
+ __attribute__ ((noreturn));
+
+static void criticalMsg (const char fmt[], ...)
+ __attribute__ ((format (printf, 1, 2)));
-/* The VM handle. This is set in GtkToolkitMain.gtkInit */
-JavaVM *gdk_vm;
+static void tracing (const char fmt[], ...)
+ __attribute__ ((format (printf, 1, 2)));
+static jint javaPriorityLevel (GThreadPriority priority)
+ __attribute__ ((const));
/************************************************************************/
-/* Utilities to reflect exceptions back to the VM */
+/* Trouble-handling, including utilities to reflect exceptions */
+/* back to the VM. Also some status reporting. */
/************************************************************************/
-/* This function checks for a pending exception, and rethrows it with
+/* How are we going to handle problems?
+
+ There are several approaches:
+
+ 1) Report them with the GError mechanism.
+
+ (*thread_create)() is the only one of these functions that takes a
+ GError pointer. And the only G_THREAD error defined maps onto EAGAIN.
+ We don't have any errors in our (*thread_create)() implementation that
+ can be mapped to EAGAIN. So this idea is a non-starter.
+
+ 2) Reflect the exception back to the VM, wrapped in a RuntimeException.
+ This will fail sometimes, if we're so broken (BADLY_BROKEN) that we
+ fail to throw the exception.
+
+ 3) Abort execution. This is what the glib functions themselves do for
+ errors that they can't report via GError.
+
+ Enable DIE_IF_BROKEN and/or DIE_IF_BADLY_BROKEN to
+ make this the default for BROKEN and/or BADLY_BROKEN trouble.
+
+ 4) Display messages to stderr. We always do this for BADLY_BROKEN
+ trouble. The glib functions do that for errors they can't report via
+ GError.
+
+ There are some complications.
+
+ When I attempted to report a problem in g_thread_self() using g_critical (a
+ macro around g_log(), I found that g_log in turn looks for thread-private
+ data and calls g_thread_self() again.
+
+ We got a segfault, probably due to stack overflow. So, this code doesn't
+ use the g_critical() and g_error() functions any more. Nor do we use
+ g_assert(); we use the C library's assert() instead.
+*/
+
+
+#define WHERE __FILE__ ":" G_STRINGIFY(__LINE__) ": "
+
+/* This is portable to older compilers that lack variable-argument macros.
+ This used to be just g_critical(), but then we ran into the error reporting
+ problem discussed above.
+*/
+static void
+fatalMsg (const char fmt[], ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+ vfprintf (stderr, fmt, ap);
+ va_end (ap);
+ fputs ("\nAborting execution\n", stderr);
+ abort ();
+}
+
+
+static void
+criticalMsg (const char fmt[], ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+ vfprintf (stderr, fmt, ap);
+ va_end (ap);
+ putc ('\n', stderr);
+}
+
+/* Unlike the other two, this one does not append a newline. This is only
+ used if one of the TRACE_ macros is defined. */
+static void
+tracing (const char fmt[], ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+ vfprintf (stderr, fmt, ap);
+ va_end (ap);
+}
+
+#define assert_not_reached() \
+ do \
+ { \
+ fputs(WHERE "You should never get here. Aborting execution.\n", \
+ stderr); \
+ abort(); \
+ } \
+ while(0)
+
+
+#if DIE_IF_BADLY_BROKEN
+#define BADLY_BROKEN fatalMsg
+#else
+#define BADLY_BROKEN criticalMsg
+/* So, the user may still attempt to recover, even though we do not advise
+ this. */
+#endif
+
+/* I find it so depressing to have to use C without varargs macros. */
+#define BADLY_BROKEN_MSG WHERE "Something fundamental" \
+ " to GNU Classpath's AWT JNI broke while we were trying to pass up a Java error message"
+
+#define BADLY_BROKEN0() \
+ BADLY_BROKEN(BADLY_BROKEN_MSG);
+#define BADLY_BROKEN1(msg) \
+ BADLY_BROKEN(BADLY_BROKEN_MSG ": " msg)
+#define BADLY_BROKEN2(msg, arg) \
+ BADLY_BROKEN(BADLY_BROKEN_MSG ": " msg, arg)
+#define BADLY_BROKEN3(msg, arg, arg2) \
+ BADLY_BROKEN(BADLY_BROKEN_MSG ": " msg, arg1, arg2)
+#define BADLY_BROKEN4(msg, arg, arg2, arg3) \
+ BADLY_BROKEN(BADLY_BROKEN_MSG ": " msg, arg1, arg2, arg3)
+
+#define DELETE_LOCAL_REF(env, ref) \
+ do \
+ { \
+ if ( DELETE_LOCAL_REFS ) \
+ { \
+ (*env)->DeleteLocalRef (env, ref); \
+ (ref) = NULL; \
+ } \
+ } \
+ while(0)
+
+/* Cached info for Exception-wrapping */
+
+jclass runtimeException_class; /* java.lang.RuntimeException */
+jmethodID runtimeException_ctor; /* constructor for it */
+
+
+/* Throw a new RuntimeException. It may wrap around an existing exception.
+ 1 if we did rethrow, -1 if we had trouble while rethrowing.
+ isBroken is always true in this case. */
+static int
+throw (JNIEnv * env, jthrowable cause, const char *message,
+ gboolean isBroken, const char *file, int line)
+{
+ jstring jmessage;
+ gboolean describedException = FALSE; /* Did we already describe the
+ exception to stderr or the
+ equivalent? */
+ jthrowable wrapper;
+
+ /* allocate local message in Java */
+ const char fmt[] = "In AWT JNI, %s (at %s:%d)";
+ size_t len = strlen (message) + strlen (file) + sizeof fmt + 25;
+ char *buf;
+
+ if (EXPLAIN_TROUBLE || (isBroken && EXPLAIN_BROKEN))
+ {
+ criticalMsg ("%s:%d: AWT JNI failure%s: %s\n", file, line,
+ isBroken ? " (BROKEN)" : "", message);
+ if (cause)
+ {
+ jthrowable currentException = (*env)->ExceptionOccurred (env);
+
+ if (cause == currentException)
+ {
+ criticalMsg ("Description follows to System.err:");
+ (*env)->ExceptionDescribe (env);
+ /* ExceptionDescribe has the side-effect of clearing the pending
+ exception; relaunch it. */
+ describedException = TRUE;
+
+ if ((*env)->Throw (env, cause))
+ {
+ BADLY_BROKEN1
+ ("Relaunching an exception with Throw failed.");
+ return -1;
+ }
+ }
+ else
+ {
+ DELETE_LOCAL_REF (env, currentException);
+ criticalMsg (WHERE
+ "currentException != cause; something else happened"
+ " while handling an exception.");
+ }
+ }
+ } /* if (EXPLAIN_TROUBLE) */
+
+ if (isBroken && DIE_IF_BROKEN)
+ fatalMsg ("%s:%d: Aborting execution; BROKEN: %s\n", file, line, message);
+
+ if ((buf = malloc (len)))
+ {
+ memset (buf, 0, len);
+ snprintf (buf, len, fmt, message, file, line);
+ jmessage = (*env)->NewStringUTF (env, buf);
+ free (buf);
+ }
+ else
+ {
+ jmessage = NULL;
+ }
+
+ /* Create the RuntimeException wrapper object and throw it. It is OK for
+ CAUSE to be NULL. */
+ wrapper = (jthrowable) (*env)->NewObject
+ (env, runtimeException_class, runtimeException_ctor, jmessage, cause);
+ DELETE_LOCAL_REF (env, jmessage);
+
+ if (!wrapper)
+ {
+ /* I think this should only happen:
+ - if there are bugs in my JNI code, or
+ - if the VM is broken, or
+ - if we run out of memory.
+ */
+ if (EXPLAIN_TROUBLE)
+ {
+ criticalMsg (WHERE "GNU Classpath: JNI NewObject() could not create"
+ " a new java.lang.RuntimeException.");
+ criticalMsg ("We were trying to warn about the following"
+ " previous failure:");
+ criticalMsg ("%s:%d: %s", file, line, message);
+ criticalMsg ("The latest (NewObject()) exception's description"
+ " follows, to System.err:");
+ (*env)->ExceptionDescribe (env);
+ }
+ BADLY_BROKEN1 ("Failure of JNI NewObject()"
+ " to make a java.lang.RuntimeException");
+ return -1;
+ }
+
+
+ /* throw it */
+ if ((*env)->Throw (env, wrapper))
+ {
+ /* Throw() should just never fail, unless we're in such severe trouble
+ that we might as well die. */
+ BADLY_BROKEN1
+ ("GNU Classpath: Failure of JNI Throw to report an Exception");
+ return -1;
+ }
+
+ DELETE_LOCAL_REF (env, wrapper);
+ return 1;
+}
+
+
+
+/* Rethrow an exception we received, wrapping it with a RuntimeException. 1
+ if we did rethrow, -1 if we had trouble while rethrowing.
+ CAUSE should be identical to the most recent exception that happened, so
+ that ExceptionDescribe will work. (Otherwise nix.) */
+static int
+rethrow (JNIEnv * env, jthrowable cause, const char *message,
+ gboolean isBroken, const char *file, int line)
+{
+ assert (cause);
+ return throw (env, cause, message, isBroken, file, line);
+}
+
+
+/* This function checks for a pending exception, and rethrows it with
* a wrapper RuntimeException to deal with possible type problems (in
* case some calling piece of code does not expect the exception being
* thrown) and to include the given extra message.
+ *
+ * Returns 0 if no problems found (so no exception thrown), 1 if we rethrew an
+ * exception. Returns -1 on failure.
*/
-static void maybe_rethrow(JNIEnv *gdk_env, char *message, char *file, int line) {
- jthrowable cause;
+static int
+maybe_rethrow (JNIEnv * env, const char *message, gboolean isBroken,
+ const char *file, int line)
+{
+ jthrowable cause = (*env)->ExceptionOccurred (env);
+ int ret = 0;
+
+ /* rethrow if an exception happened */
+ if (cause)
+ {
+ ret = rethrow (env, cause, message, isBroken, file, line);
+ DELETE_LOCAL_REF (env, cause);
+ }
+
+ return 0;
+}
+
+/* MAYBE_TROUBLE() is used to include a source location in the exception
+ message. Once we have run maybe_rethrow, if there WAS trouble,
+ return TRUE, else FALSE.
+
+ MAYBE_TROUBLE() is actually never used; all problems that throw exceptions
+ are BROKEN, at least. Nothing is recoverable :(. See the discussion of
+ possible errors at thread_create_jni_impl(). */
+#define MAYBE_TROUBLE(_env, _message) \
+ maybe_rethrow(_env, _message, FALSE, __FILE__, __LINE__)
+
+/* MAYBE_TROUBLE(), but something would be BROKEN if it were true. */
+#define MAYBE_BROKEN(_env, _message) \
+ maybe_rethrow(_env, _message, TRUE, __FILE__, __LINE__)
+
+/* Like MAYBE_TROUBLE(), TROUBLE() is never used. */
+#define TROUBLE(_env, _message) \
+ rethrow(_env, (*env)->ExceptionOccurred (env), _message, FALSE, \
+ __FILE__, __LINE__)
+
+#define BROKEN(_env, _message) \
+ rethrow (_env, (*env)->ExceptionOccurred (env), _message, TRUE, \
+ __FILE__, __LINE__)
+
+/* Like MAYBE_TROUBLE(), NEW_TROUBLE() is never used. */
+#define NEW_TROUBLE(_env, _message) \
+ throw (_env, NULL, _message, FALSE, __FILE__, __LINE__)
+
+#define NEW_BROKEN(_env, _message) \
+ throw (_env, NULL, _message, TRUE, __FILE__, __LINE__)
+
+/* Like MAYBE_TROUBLE(), RETHROW_CAUSE() is never used. */
+#define RETHROW_CAUSE(_env, _cause, _message) \
+ rethrow (_env, _cause, _message, FALSE, __FILE__, __LINE__)
+
+#define BROKEN_CAUSE(_env, _cause, _message) \
+ rethrow (_env, _cause, _message, TRUE, __FILE__, __LINE__)
+
+/* Macros to handle the possibility that someone might have called one of the
+ GThreadFunctions API functions with a Java exception pending. It is
+ generally discouraged to continue to use JNI after a Java exception has
+ been raised. Sun's JNI book advises that one trap JNI errors immediately
+ and not continue with an exception pending.
+
+ These are #if'd out for these reasons:
+
+ 1) They do not work in the C '89 subset that Classpath is currently
+ (2004 May 10) sticking to; HIDE_OLD_TROUBLE() includes a declaration
+ that should be in scope for the rest of the function, so it needs a
+ language version that lets you mix declarations and statements. (This
+ could be worked around if it were important.)
+
+ 2) They chew up more time and resources.
+
+ 3) There does not ever seem to be old trouble -- the assertion in
+ HIDE_OLD_TROUBLE never goes off.
+
+ You will want to re-enable them if this code needs to be used in a context
+ where old exceptions might be pending when the GThread functions are
+ called.
+
+ The implementations in this file are responsible for skipping around calls
+ to SHOW_OLD_TROUBLE() if they've raised exceptions during the call. So, if
+ we reach SHOW_OLD_TROUBLE, we are guaranteed that there are no exceptions
+ pending. */
+#if 1
+#define HIDE_OLD_TROUBLE(env) \
+ assert ( NULL == (*env)->ExceptionOccurred (env) )
+
+#define SHOW_OLD_TROUBLE() \
+ assert ( NULL == (*env)->ExceptionOccurred (env) )
+#else /* 0 */
+#define HIDE_OLD_TROUBLE(env) \
+ jthrowable savedTrouble = (*env)->ExceptionOccurred (env); \
+ (*env)->ExceptionClear (env);
+
+#define SHOW_OLD_TROUBLE() do \
+{ \
+ assert ( NULL == (*env)->ExceptionOccurred (env) ) \
+ if (savedTrouble) \
+ { \
+ if ((*env)->Throw (env, savedTrouble)) \
+ BADLY_BROKEN ("ReThrowing the savedTrouble failed"); \
+ } \
+ DELETE_LOCAL_REF (env, savedTrouble); \
+} while(0)
+
+#endif /* 0 */
+
+/* Set up the cache of jclass and jmethodID primitives we need
+ in order to throw new exceptions and rethrow exceptions. We do this
+ independently of the other caching. We need to have this cache set up
+ first, so that we can then report errors properly.
+
+ If any errors while setting up the error cache, the world is BADLY_BROKEN.
+
+ May be called more than once.
+
+ Returns -1 if the cache was not initialized properly, 1 if it was.
+*/
+static int
+setup_exception_cache (JNIEnv * env)
+{
+ static int exception_cache_initialized = 0; /* -1 for trouble, 1 for proper
+ init. */
+
+ jclass lcl_class; /* a class used for local refs */
+
+ if (exception_cache_initialized)
+ return exception_cache_initialized;
+ lcl_class = (*env)->FindClass (env, "java/lang/RuntimeException");
+ if ( ! lcl_class )
+ {
+ BADLY_BROKEN1 ("Broken Class library or VM?"
+ " Couldn't find java/lang/RuntimeException");
+ return exception_cache_initialized = -1;
+ }
+ /* Pin it down. */
+ runtimeException_class = (jclass) (*env)->NewGlobalRef (env, lcl_class);
+ DELETE_LOCAL_REF (env, lcl_class);
+ if (!runtimeException_class)
+ {
+ BADLY_BROKEN1 ("Serious trouble: could not turn"
+ " java.lang.RuntimeException into a global reference");
+ return exception_cache_initialized = -1;
+ }
+
+ runtimeException_ctor =
+ (*env)->GetMethodID (env, runtimeException_class, "<init>",
+ "(Ljava/lang/String;Ljava/lang/Throwable;)V");
+ if ( ! runtimeException_ctor )
+ {
+ BADLY_BROKEN1 ("Serious trouble: classpath couldn't find a"
+ " two-arg constructor for java/lang/RuntimeException");
+ return exception_cache_initialized = -1;
+ }
+
+ return exception_cache_initialized = 1;
+}
+
+
+/**********************************************************/
+/***** The main cache *************************************/
+/**********************************************************/
+
+/** This is a cache of all classes, methods, and field IDs that we use during
+ the run. We maintain a permanent global reference to each of the classes
+ we cache, since otherwise the (local) jclass that refers to that class
+ would go out of scope and possibly be reused in further calls.
+
+ The permanent global reference also achieves the secondary goal of
+ protecting the validity of the methods and field IDs in case the classes
+ were otherwise unloaded and then later loaded again. Obviously, this will
+ never happen to classes such as java.lang.Thread and java.lang.Object, but
+ the primary reason for maintaining permanent global refs is sitll valid.
+
+ The code in jnilink.c has a similar objective. TODO: Consider using that
+ code instead.
+
+ --Steven Augart
+*/
+
+/* All of these are cached classes and method IDs: */
+/* java.lang.Object */
+static jclass obj_class; /* java.lang.Object */
+static jmethodID obj_ctor; /* no-arg Constructor for java.lang.Object */
+static jmethodID obj_notify_mth; /* java.lang.Object.notify() */
+static jmethodID obj_notifyall_mth; /* java.lang.Object.notifyall() */
+static jmethodID obj_wait_mth; /* java.lang.Object.wait() */
+static jmethodID obj_wait_nanotime_mth; /* java.lang.Object.wait(JI) */
+
+/* GThreadMutex and its methods */
+static jclass mutex_class;
+static jmethodID mutex_ctor;
+static jfieldID mutex_lockForPotentialLockers_fld;
+static jfieldID mutex_potentialLockers_fld;
+
+/* java.lang.Thread and its methods*/
+static jclass thread_class; /* java.lang.Thread */
+static jmethodID thread_current_mth; /* Thread.currentThread() */
+static jmethodID thread_equals_mth; /* Thread.equals() */
+static jmethodID thread_join_mth; /* Thread.join() */
+static jmethodID thread_setPriority_mth; /* Thread.setPriority() */
+static jmethodID thread_stop_mth; /* Thread.stop() */
+static jmethodID thread_yield_mth; /* Thread.yield() */
+
+/* java.lang.ThreadLocal and its methods */
+static jclass threadlocal_class; /* java.lang.ThreadLocal */
+static jmethodID threadlocal_ctor; /* Its constructor */
+static jmethodID threadlocal_set_mth; /* ThreadLocal.set() */
+static jmethodID threadlocal_get_mth; /* ThreadLocal.get() */
+
+/* java.lang.Long and its methods */
+static jclass long_class; /* java.lang.Long */
+static jmethodID long_ctor; /* constructor for it: (J) */
+static jmethodID long_longValue_mth; /* longValue()J */
+
+
+/* GThreadNativeMethodRunner */
+static jclass runner_class;
+static jmethodID runner_ctor;
+static jmethodID runner_threadToThreadID_mth;
+static jmethodID runner_threadIDToThread_mth;
+static jmethodID runner_deRegisterJoinable_mth;
+static jmethodID runner_start_mth; /* Inherited Thread.start() */
+
+
+/* java.lang.InterruptedException */
+static jclass interrupted_exception_class;
+
+
+
+
+/* Returns a negative value if there was trouble during initialization.
+ Returns a positive value of the cache was initialized correctly.
+ Never returns zero. */
+static int
+setup_cache (JNIEnv * env)
+{
+ jclass lcl_class;
+ static int initialized = 0; /* 1 means initialized, 0 means uninitialized,
+ -1 means mis-initialized */
+
+ if (initialized)
+ return initialized;
+
+ /* make sure we can report on trouble */
+ if (setup_exception_cache (env) < 0)
+ return initialized = -1;
+
+#ifdef JNI_VERSION_1_2
+ if (HAVE_JNI_VERSION_1_2)
+ assert ( ! (*env)->ExceptionCheck (env));
+ else
+#endif
+ assert ( ! (*env)->ExceptionOccurred (env));
+
+ /* java.lang.Object and its methods */
+ lcl_class = (*env)->FindClass (env, "java/lang/Object");
+ if (!lcl_class)
+ {
+ BROKEN (env, "cannot find java.lang.Object");
+ return initialized = -1;
+ }
+
+ /* Pin it down. */
+ obj_class = (jclass) (*env)->NewGlobalRef (env, lcl_class);
+ DELETE_LOCAL_REF (env, lcl_class);
+ if (!obj_class)
+ {
+ BROKEN (env, "Cannot get a global reference to java.lang.Object");
+ return initialized = -1;
+ }
+
+ obj_ctor = (*env)->GetMethodID (env, obj_class, "<init>", "()V");
+ if (!obj_ctor)
+ {
+ BROKEN (env, "cannot find constructor for java.lang.Object");
+ return initialized = -1;
+ }
+
+ obj_notify_mth = (*env)->GetMethodID (env, obj_class, "notify", "()V");
+ if ( ! obj_notify_mth )
+ {
+ BROKEN (env, "cannot find java.lang.Object.notify()V");
+ return initialized = -1;
+ }
+
+ obj_notifyall_mth =
+ (*env)->GetMethodID (env, obj_class, "notifyAll", "()V");
+ if ( ! obj_notifyall_mth)
+ {
+ BROKEN (env, "cannot find java.lang.Object.notifyall()V");
+ return initialized = -1;
+ }
+
+ obj_wait_mth = (*env)->GetMethodID (env, obj_class, "wait", "()V");
+ if ( ! obj_wait_mth )
+ {
+ BROKEN (env, "cannot find Object.<wait()V>");
+ return initialized = -1;
+ }
+
+ obj_wait_nanotime_mth =
+ (*env)->GetMethodID (env, obj_class, "wait", "(JI)V");
+ if ( ! obj_wait_nanotime_mth )
+ {
+ BROKEN (env, "cannot find Object.<wait(JI)V>");
+ return initialized = -1;
+ }
+
+ /* GThreadMutex and its methods */
+ lcl_class = (*env)->FindClass (env, "gnu/java/awt/peer/gtk/GThreadMutex");
+ if ( ! lcl_class)
+ {
+ BROKEN (env, "cannot find gnu.java.awt.peer.gtk.GThreadMutex");
+ return initialized = -1;
+ }
+ /* Pin it down. */
+ mutex_class = (jclass) (*env)->NewGlobalRef (env, lcl_class);
+ DELETE_LOCAL_REF (env, lcl_class);
+ if ( ! mutex_class)
+ {
+ BROKEN (env, "Cannot get a global reference to GThreadMutex");
+ return initialized = -1;
+ }
+
+ mutex_ctor = (*env)->GetMethodID (env, mutex_class, "<init>", "()V");
+ if ( ! mutex_ctor)
+ {
+ BROKEN (env, "cannot find zero-arg constructor for GThreadMutex");
+ return initialized = -1;
+ }
+
+ mutex_potentialLockers_fld = (*env)->GetFieldID
+ (env, mutex_class, "potentialLockers", "I");
+ if ( ! mutex_class )
+ {
+ BROKEN (env, "cannot find GThreadMutex.potentialLockers");
+ return initialized = -1;
+ }
+
+ if (! (mutex_lockForPotentialLockers_fld = (*env)->GetFieldID
+ (env, mutex_class, "lockForPotentialLockers", "Ljava/lang/Object;")))
+ {
+ BROKEN (env, "cannot find GThreadMutex.lockForPotentialLockers");
+ return initialized = -1;
+ }
+
+
+ /* java.lang.Thread */
+ if (! (lcl_class = (*env)->FindClass (env, "java/lang/Thread")))
+ {
+ BROKEN (env, "cannot find java.lang.Thread");
+ return initialized = -1;
+ }
+
+ /* Pin it down. */
+ thread_class = (jclass) (*env)->NewGlobalRef (env, lcl_class);
+ DELETE_LOCAL_REF (env, lcl_class);
+ if (!thread_class)
+ {
+ BROKEN (env, "Cannot get a global reference to java.lang.Thread");
+ return initialized = -1;
+ }
+
+ thread_current_mth =
+ (*env)->GetStaticMethodID (env, thread_class, "currentThread",
+ "()Ljava/lang/Thread;");
+ if (!thread_current_mth)
+ {
+ BROKEN (env, "cannot find Thread.currentThread() method");
+ return initialized = -1;
+ }
+
+ thread_equals_mth =
+ (*env)->GetMethodID (env, thread_class, "equals", "(Ljava/lang/Object;)Z");
+ if (!thread_equals_mth)
+ {
+ BROKEN (env, "cannot find Thread.equals() method");
+ return initialized = -1;
+ }
+
+ thread_join_mth = (*env)->GetMethodID (env, thread_class, "join", "()V");
+ if (!thread_join_mth)
+ {
+ BROKEN (env, "cannot find Thread.join() method");
+ return initialized = -1;
+ }
+
+ thread_stop_mth = (*env)->GetMethodID (env, thread_class, "stop", "()V");
+ if ( ! thread_stop_mth )
+ {
+ BROKEN (env, "cannot find Thread.stop() method");
+ return initialized = -1;
+ }
+
+ thread_setPriority_mth =
+ (*env)->GetMethodID (env, thread_class, "setPriority", "(I)V");
+ if ( ! thread_setPriority_mth )
+ {
+ BROKEN (env, "cannot find Thread.setPriority() method");
+ return initialized = -1;
+ }
+
+ thread_yield_mth =
+ (*env)->GetStaticMethodID (env, thread_class, "yield", "()V");
+ if ( ! thread_yield_mth )
+ {
+ BROKEN (env, "cannot find Thread.yield() method");
+ return initialized = -1;
+ }
+
+ /* java.lang.ThreadLocal */
+ lcl_class = (*env)->FindClass (env, "java/lang/ThreadLocal");
+ if ( ! lcl_class )
+ {
+ BROKEN (env, "cannot find class java.lang.ThreadLocal");
+ return initialized = -1;
+ }
+
+ /* Pin it down. */
+ threadlocal_class = (jclass) (*env)->NewGlobalRef (env, lcl_class);
+ DELETE_LOCAL_REF (env, lcl_class);
+ if ( ! threadlocal_class )
+ {
+ BROKEN (env, "Cannot get a global reference to java.lang.ThreadLocal");
+ return initialized = -1;
+ }
+
+ threadlocal_ctor = (*env)->GetMethodID (env, threadlocal_class,
+ "<init>", "()V");
+ if ( ! threadlocal_ctor )
+ {
+ BROKEN (env, "cannot find ThreadLocal.<init>()V");
+ return initialized = -1;
+ }
+
+ threadlocal_get_mth = (*env)->GetMethodID (env, threadlocal_class,
+ "get", "()Ljava/lang/Object;");
+ if ( ! threadlocal_get_mth )
+ {
+ BROKEN (env, "cannot find java.lang.ThreadLocal.get()Object");
+ return initialized = -1;
+ }
+
+ threadlocal_set_mth = (*env)->GetMethodID (env, threadlocal_class,
+ "set", "(Ljava/lang/Object;)V");
+ if ( ! threadlocal_set_mth )
+ {
+ BROKEN (env, "cannot find ThreadLocal.set(Object)V");
+ return initialized = -1;
+ }
+
+ /* java.lang.Long */
+ lcl_class = (*env)->FindClass (env, "java/lang/Long");
+ if ( ! lcl_class )
+ {
+ BROKEN (env, "cannot find class java.lang.Long");
+ return initialized = -1;
+ }
+
+ /* Pin it down. */
+ long_class = (jclass) (*env)->NewGlobalRef (env, lcl_class);
+ DELETE_LOCAL_REF (env, lcl_class);
+ if (!long_class)
+ {
+ BROKEN (env, "Cannot get a global reference to java.lang.Long");
+ return initialized = -1;
+ }
+
+ long_ctor = (*env)->GetMethodID (env, long_class, "<init>", "(J)V");
+ if (!long_ctor)
+ {
+ BROKEN (env, "cannot find method java.lang.Long.<init>(J)V");
+ return initialized = -1;
+ }
+
+ long_longValue_mth =
+ (*env)->GetMethodID (env, long_class, "longValue", "()J");
+ if (!long_longValue_mth)
+ {
+ BROKEN (env, "cannot find method java.lang.Long.longValue()J");
+ return initialized = -1;
+ }
+
+
+ /* GThreadNativeMethodRunner */
+ lcl_class =
+ (*env)->FindClass (env,
+ "gnu/java/awt/peer/gtk/GThreadNativeMethodRunner");
+ if ( ! lcl_class )
+ {
+ BROKEN (env,
+ "cannot find gnu.java.awt.peer.gtk.GThreadNativeMethodRunner");
+ return initialized = -1;
+ }
+
+ /* Pin it down. */
+ runner_class = (jclass) (*env)->NewGlobalRef (env, lcl_class);
+ DELETE_LOCAL_REF (env, lcl_class);
+ if (!runner_class)
+ {
+ BROKEN (env,
+ "Cannot get a global reference to the class GThreadNativeMethodRunner");
+ return initialized = -1;
+ }
+
+ runner_ctor = (*env)->GetMethodID (env, runner_class, "<init>", "(JJZ)V");
+ if ( ! runner_ctor )
+ {
+ BROKEN (env,
+ "cannot find method GThreadNativeMethodRunner.<init>(JJZ)");
+ return initialized = -1;
+ }
+
+ runner_start_mth = (*env)->GetMethodID (env, runner_class, "start", "()V");
+ if ( ! runner_start_mth )
+ {
+ BROKEN (env, "cannot find method GThreadNativeMethodRunner.start()V");
+ return initialized = -1;
+ }
+
+
+ runner_threadToThreadID_mth =
+ (*env)->GetStaticMethodID (env, runner_class,
+ "threadToThreadID", "(Ljava/lang/Thread;)I");
+ if ( ! runner_threadToThreadID_mth )
+ {
+ BROKEN (env,
+ "cannot find method GThreadNativeMethodRunner.threadToThreadID(java.lang.Thread)I");
+ return initialized = -1;
+ }
+
+
+ runner_threadIDToThread_mth =
+ (*env)->GetStaticMethodID (env, runner_class,
+ "threadIDToThread", "(I)Ljava/lang/Thread;");
+ if ( ! runner_threadIDToThread_mth )
+ {
+ BROKEN (env,
+ "cannot find method GThreadNativeMethodRunner.threadIDToThread(I)java.lang.Thread");
+ return initialized = -1;
+ }
+
+
+ runner_deRegisterJoinable_mth =
+ (*env)->GetStaticMethodID (env, runner_class, "deRegisterJoinable",
+ "(Ljava/lang/Thread;)V");
+ if (!runner_deRegisterJoinable_mth)
+ {
+ BROKEN (env,
+ "cannot find method GThreadNativeMethodRunner.deRegisterJoinable(java.lang.Thread)V");
+ return initialized = -1;
+ }
+
+
+ /* java.lang.InterruptedException */
+ lcl_class = (*env)->FindClass (env, "java/lang/InterruptedException");
+ if ( ! lcl_class )
+ {
+ BROKEN (env, "cannot find class java.lang.InterruptedException");
+ return initialized = -1;
+ }
+
+ /* Pin it down. */
+ interrupted_exception_class = (jclass) (*env)->NewGlobalRef (env, lcl_class);
+ DELETE_LOCAL_REF (env, lcl_class);
+ if (!interrupted_exception_class)
+ {
+ BROKEN (env, "Cannot make a global reference"
+ " to java.lang.InterruptedException");
+ return initialized = -1;
+ }
+
+#ifdef JNI_VERSION_1_2
+ if (HAVE_JNI_VERSION_1_2)
+ assert ( ! (*env)->ExceptionCheck (env));
+ else
+#endif
+ assert ( ! (*env)->ExceptionOccurred (env));
+
+
+ return initialized = 1;
+}
+
+
- jstring jmessage;
- jclass obj_class;
- jobject obj;
- jmethodID ctor;
- int len;
- char *buf;
-
- /* rethrow if an exception happened */
- if ((cause = (*gdk_env)->ExceptionOccurred(gdk_env)) != NULL)
- {
-
- /* allocate local message in Java */
- len = strlen(message) + strlen(file) + 25;
- buf = (char *) malloc(len);
- if (buf != NULL)
- {
- bzero(buf, len);
- sprintf(buf, "%s (at %s:%d)", message, file, line);
- jmessage = (*gdk_env)->NewStringUTF(gdk_env, buf);
- free(buf);
- }
- else
- jmessage = NULL;
-
- /* create RuntimeException wrapper object */
- obj_class = (*gdk_env)->FindClass (gdk_env,
- "java/lang/RuntimeException");
- ctor = (*gdk_env)->GetMethodID(gdk_env, obj_class, "<init>",
- "(Ljava/langString;Ljava/lang/Throwable)V");
- obj = (*gdk_env)->NewObject (gdk_env, obj_class, ctor, jmessage, cause);
-
- /* throw it */
- (*gdk_env)->Throw(gdk_env, (jthrowable)obj);
- }
-}
-
-/* This macro is used to include a source location in the exception message */
-#define MAYBE_RETHROW(_class, _message) \
-maybe_rethrow(_class, _message, __FILE__, __LINE__)
/************************************************************************/
/* Utilities to allocate and free java.lang.Objects */
/************************************************************************/
-/* Both the mutexes and the condition variables are java.lang.Object objects,
+/* The condition variables are java.lang.Object objects,
* which this method allocates and returns a global ref. Note that global
* refs must be explicitly freed (isn't C fun?).
*/
-static jobject *allocatePlainObject() {
- jclass obj_class;
- jobject *obj;
- JNIEnv *gdk_env;
- jmethodID ctor;
-
- (*gdk_vm)->GetEnv(gdk_vm, (void **)&gdk_env, JNI_VERSION_1_1);
+static jobject
+allocatePlainObject (JNIEnv * env)
+{
+ jobject lcl_obj, global_obj;
- obj_class = (*gdk_env)->FindClass (gdk_env, "java/lang/Object");
- MAYBE_RETHROW(gdk_env, "cannot find Object");
+ lcl_obj = (*env)->NewObject (env, obj_class, obj_ctor);
+ if (!lcl_obj)
+ {
+ BROKEN (env, "cannot allocate object");
+ return NULL;
+ }
- ctor = (*gdk_env)->GetMethodID(gdk_env, obj_class, "<init>", "()V");
- MAYBE_RETHROW(gdk_env, "cannot find constructor");
+ global_obj = (*env)->NewGlobalRef (env, lcl_obj);
+ DELETE_LOCAL_REF (env, lcl_obj);
+ if (!global_obj)
+ {
+ NEW_BROKEN (env, "cannot make global ref for a new plain Java object");
+ /* Deliberate fall-through */
+ }
- obj = (jobject *) g_malloc (sizeof (jobject));
- *obj = (*gdk_env)->NewObject (gdk_env, obj_class, ctor);
- MAYBE_RETHROW(gdk_env, "cannot allocate object");
-
- *obj = (*gdk_env)->NewGlobalRef (gdk_env, *obj);
- MAYBE_RETHROW(gdk_env, "cannot make global ref");
+ return global_obj;
+}
- return obj;
+/* Frees any Java object given a global ref (isn't C fun?) */
+static void
+freeObject (JNIEnv * env, jobject obj)
+{
+ if (obj)
+ {
+ (*env)->DeleteGlobalRef (env, obj);
+ /* DeleteGlobalRef can never fail */
+ }
}
-/* Frees a Java object given a global ref (isn't C fun?) */
-static void freePlainObject(jobject *obj) {
- JNIEnv *gdk_env;
- if (obj) {
- (*gdk_vm)->GetEnv(gdk_vm, (void **)&gdk_env, JNI_VERSION_1_1);
+/************************************************************************/
+/* Utilities to allocate and free Java mutexes */
+/************************************************************************/
- (*gdk_env)->DeleteGlobalRef (gdk_env, *obj);
- MAYBE_RETHROW(gdk_env, "cannot delete global ref");
-
- g_free (obj);
- }
+/* The mutexes are gnu.java.awt.peer.gtk.GThreadMutex objects,
+ * which this method allocates and returns a global ref. Note that global
+ * refs must be explicitly freed (isn't C fun?).
+ *
+ * Free this with freeObject()
+ */
+static jobject
+allocateMutexObject (JNIEnv * env)
+{
+ jobject lcl_obj, global_obj;
+
+ lcl_obj = (*env)->NewObject (env, mutex_class, mutex_ctor);
+ if (!lcl_obj)
+ {
+ BROKEN (env, "cannot allocate a GThreadMutex");
+ return NULL;
+ }
+
+ global_obj = (*env)->NewGlobalRef (env, lcl_obj);
+ DELETE_LOCAL_REF (env, lcl_obj);
+ if (!global_obj)
+ {
+ NEW_BROKEN (env, "cannot make global ref");
+ /* Deliberate fallthrough */
+ }
+
+ return global_obj;
}
@@ -184,195 +1208,746 @@ static void freePlainObject(jobject *obj) {
/************************************************************************/
/* Lock a Java object */
-static void takeLock(JNIEnv *gdk_env, void *mutex) {
- (*gdk_env)->MonitorEnter (gdk_env, *((jobject *)mutex));
- MAYBE_RETHROW(gdk_env, "cannot get lock");
+#define ENTER_MONITOR(env, m) \
+ enterMonitor(env, m, G_STRINGIFY(m))
+
+/* Return -1 on failure, 0 on success. */
+static int
+enterMonitor (JNIEnv * env, jobject monitorObj, const char monName[])
+{
+ if (TRACE_MONITORS)
+ tracing (" <MonitorEnter(%s)>", monName);
+ assert (monitorObj);
+ if ((*env)->MonitorEnter (env, monitorObj) < 0)
+ {
+ BROKEN (env, "cannot enter monitor");
+ return -1;
+ }
+ return 0;
}
+
/* Unlock a Java object */
-static void releaseLock(JNIEnv *gdk_env, void *mutex) {
- (*gdk_env)->MonitorExit (gdk_env, *((jobject *)mutex));
- MAYBE_RETHROW(gdk_env, "cannot release lock");
+#define EXIT_MONITOR(env, m) \
+ exitMonitor(env, m, G_STRINGIFY(m))
+
+static int
+exitMonitor (JNIEnv * env, jobject mutexObj, const char monName[])
+{
+ if (TRACE_MONITORS)
+ tracing (" <MonitorExit(%s)>", monName);
+ assert (mutexObj);
+ if ((*env)->MonitorExit (env, mutexObj) < 0)
+ {
+ BROKEN (env, "cannot exit monitor ");
+ return -1;
+ }
+ return 0;
}
-/* Create a mutex, which is a java.lang.Object for us */
-static GMutex *g_mutex_new_jni_impl (void) {
- return (GMutex*) allocatePlainObject();
+
+/************************************************************************/
+/* Miscellaneous utilities */
+/************************************************************************/
+
+/* Get the Java Thread object that corresponds to a particular thread ID.
+ A negative thread Id gives us a null object.
+
+ Returns a local reference.
+*/
+static jobject
+getThreadFromThreadID (JNIEnv * env, gpointer gThreadID)
+{
+ jint threadNum = (jint) gThreadID;
+ jobject thread;
+
+ if (threadNum < 0)
+ {
+ NEW_BROKEN (env, "getThreadFromThreadID asked to look up"
+ " a negative thread index");
+ return NULL;
+ }
+
+ thread = (*env)->CallStaticObjectMethod
+ (env, runner_class, runner_threadIDToThread_mth, threadNum);
+
+ if (MAYBE_BROKEN (env, "cannot get Thread for threadID "))
+ return NULL;
+
+ return thread;
+}
+
+/** Return the unique threadID of THREAD.
+
+ Error handling: Return (gpointer) -1 on all failures,
+ and propagate an exception.
+*/
+static gpointer
+getThreadIDFromThread (JNIEnv * env, jobject thread)
+{
+ jint threadNum;
+
+ if (ENABLE_EXPENSIVE_ASSERTIONS)
+ assert ((*env)->IsInstanceOf (env, thread, thread_class));
+
+ HIDE_OLD_TROUBLE (env);
+
+ threadNum = (*env)->CallStaticIntMethod
+ (env, runner_class, runner_threadToThreadID_mth, thread);
+
+ if (MAYBE_BROKEN (env, "cannot get ThreadID for a Thread "))
+ {
+ threadNum = -1;
+ goto done;
+ }
+
+
+ SHOW_OLD_TROUBLE ();
+
+done:
+ return (gpointer) threadNum;
+}
+
+
+/************************************************************************/
+/* The Actual JNI functions that we pass to the function vector. */
+/************************************************************************/
+
+
+/************************************************************************/
+/* Mutex Functions */
+/************************************************************************/
+
+/*** Mutex Utilities ****/
+struct mutexObj_cache
+{
+ jobject lockForPotentialLockersObj; /* Lock for the potentialLockers
+ field. Local reference. */
+ jobject lockObj; /* The real lock we use. This is a GLOBAL
+ reference and must not be freed. */
+};
+
+/* Initialize the cache of sub-locks for a particular mutex object.
+
+ -1 on error, 0 on success. The caller is not responsible for freeing the
+ partially-populated cache in case of failure (but in practice does anyway)
+ (This actually never fails, though, since GetObjectField allegedly never
+ fails.)
+
+ Guaranteed to leave all fields of the cache initialized, even if only to
+ zero.
+*/
+static int
+populate_mutexObj_cache (JNIEnv * env, jobject mutexObj,
+ struct mutexObj_cache *mcache)
+{
+ mcache->lockObj = mutexObj; /* the mutexObj is its own lock. */
+ assert (mcache->lockObj);
+
+ mcache->lockForPotentialLockersObj = (*env)->GetObjectField
+ (env, mutexObj, mutex_lockForPotentialLockers_fld);
+ /* GetObjectField can never fail. */
+
+ /* Retrieving a NULL object could only happen if we somehow got a
+ a mutex object that was not properly intialized. */
+ assert (mcache->lockForPotentialLockersObj);
+
+ return 0;
+}
+
+
+/* Clean out the mutexObj_cache, even if it was never populated. */
+static void
+clean_mutexObj_cache (JNIEnv * env, struct mutexObj_cache *mcache)
+{
+ /* OK to pass NULL refs to DELETE_LOCAL_REF */
+ DELETE_LOCAL_REF (env, mcache->lockForPotentialLockersObj);
+ /* mcache->lockObj is a GLOBAL reference. */
+ mcache->lockObj = NULL;
+}
+
+/* -1 on failure, 0 on success.
+ The mutexObj_cache is already populated for this particular object. */
+static int
+mutexObj_lock (JNIEnv * env, jobject mutexObj, struct mutexObj_cache *mcache)
+{
+ jint potentialLockers;
+
+ if (ENTER_MONITOR (env, mcache->lockForPotentialLockersObj))
+ return -1;
+
+ assert(mutexObj);
+ potentialLockers =
+ (*env)->GetIntField (env, mutexObj, mutex_potentialLockers_fld);
+ /* GetIntField() never fails. */
+
+ ++potentialLockers;
+
+ (*env)->SetIntField
+ (env, mutexObj, mutex_potentialLockers_fld, potentialLockers);
+
+ if (EXIT_MONITOR (env, mcache->lockForPotentialLockersObj))
+ return -1;
+
+ if (ENTER_MONITOR (env, mcache->lockObj))
+ return -1;
+
+ SHOW_OLD_TROUBLE ();
+
+ return 0;
+}
+
+/* Unlock a GMutex, once we're already in JNI and have already gotten the
+ mutexObj for it. This skips the messages that TRACE_API_CALLS would
+ print.
+
+ Returns -1 on error, 0 on success. */
+static int
+mutexObj_unlock (JNIEnv * env, jobject mutexObj,
+ struct mutexObj_cache *mcache)
+{
+ jint potentialLockers;
+ int ret = -1; /* assume failure until we suceed. */
+
+ /* Free the lock first, so that someone waiting for the lock can get it
+ ASAP. */
+ /* This is guaranteed not to block. */
+ if (EXIT_MONITOR (env, mcache->lockObj) < 0)
+ goto done;
+
+ /* Kick down potentialLockers by one. We do this AFTER we free the lock, so
+ that we hold it no longer than necessary. */
+ if (ENTER_MONITOR (env, mcache->lockForPotentialLockersObj) < 0)
+ goto done;
+
+ potentialLockers = (*env)->GetIntField
+ (env, mutexObj, mutex_potentialLockers_fld);
+ /* GetIntField never fails */
+
+ assert (potentialLockers >= 1);
+ --potentialLockers;
+
+ (*env)->SetIntField
+ (env, mutexObj, mutex_potentialLockers_fld, potentialLockers);
+ /* Never fails, so the JNI book says. */
+
+ /* Clean up. */
+ if (EXIT_MONITOR (env, mcache->lockForPotentialLockersObj) < 0)
+ goto done;
+ ret = 0;
+
+done:
+ return ret;
+}
+
+/*** Mutex Implementations ****/
+
+/* Create a mutex, which is a java.lang.Object for us.
+ In case of failure, we'll return NULL. Which will implicitly
+ cause future calls to fail. */
+static GMutex *
+mutex_new_jni_impl (void)
+{
+ jobject mutexObj;
+ JNIEnv *env;
+ union env_union e;
+
+ if (TRACE_API_CALLS)
+ tracing ("mutex_new_jni_impl()");
+
+ e.jni_env = &env;
+ (*the_vm)->GetEnv (the_vm, e.void_env, JNI_VERSION_1_1);
+
+ if (setup_cache (env) < 0)
+ {
+ mutexObj = NULL;
+ goto done;
+ }
+
+ mutexObj = allocateMutexObject (env);
+
+done:
+ if (TRACE_API_CALLS)
+ tracing (" ==> %p \n", mutexObj);
+
+ return (GMutex *) mutexObj;
+
}
/* Lock a mutex. */
-static void g_mutex_lock_jni_impl (GMutex *mutex __attribute__((unused))) {
- JNIEnv *gdk_env;
+static void
+mutex_lock_jni_impl (GMutex * mutex)
+{
+ struct mutexObj_cache mcache;
+ jobject mutexObj = (jobject) mutex;
+ JNIEnv *env;
+ union env_union e;
+
+ if (TRACE_API_CALLS)
+ tracing ("mutex_lock_jni_impl( mutexObj = %p )", mutexObj);
+
+ assert (mutexObj);
+ e.jni_env = &env;
+ (*the_vm)->GetEnv (the_vm, e.void_env, JNI_VERSION_1_1);
+
+ if (setup_cache (env) < 0)
+ goto done;
- (*gdk_vm)->GetEnv(gdk_vm, (void **)&gdk_env, JNI_VERSION_1_1);
+ HIDE_OLD_TROUBLE (env);
- takeLock(gdk_env, mutex);
+ if (populate_mutexObj_cache (env, mutexObj, &mcache) < 0)
+ goto done;
+
+ mutexObj_lock (env, mutexObj, &mcache);
+ /* No need to error check; we've already reported it in any case. */
+
+done:
+ clean_mutexObj_cache (env, &mcache);
+ if (TRACE_API_CALLS)
+ tracing (" ==> VOID \n");
}
-/* Try to lock a mutex. Actually, do not try because Java objects
- * do not provide such an interface. To be at least minimally correct,
- * pretend we tried and failed.
- */
-static gboolean g_mutex_trylock_jni_impl
- (GMutex *mutex __attribute__((unused)))
+
+/* Try to lock a mutex. Return TRUE if we succeed, FALSE if we fail.
+ FALSE on error. */
+static gboolean
+mutex_trylock_jni_impl (GMutex * gmutex)
{
- /* XXX Shall we implement this in a VM-specific way under a flag? */
- return FALSE;
+ jobject mutexObj = (jobject) gmutex;
+ jint potentialLockers;
+ gboolean ret = FALSE;
+ JNIEnv *env;
+ union env_union e;
+ struct mutexObj_cache mcache;
+
+ if (TRACE_API_CALLS)
+ tracing ("mutex_trylock_jni_impl(mutexObj=%p)", mutexObj);
+
+ assert (mutexObj);
+
+ e.jni_env = &env;
+ (*the_vm)->GetEnv (the_vm, e.void_env, JNI_VERSION_1_1);
+ if (setup_cache (env) < 0)
+ goto done;
+ HIDE_OLD_TROUBLE (env);
+
+ if (populate_mutexObj_cache (env, mutexObj, &mcache) < 0)
+ goto done;
+
+ if (ENTER_MONITOR (env, mcache.lockForPotentialLockersObj))
+ goto done;
+
+ potentialLockers = (*env)->GetIntField
+ (env, mutexObj, mutex_potentialLockers_fld);
+
+ assert (potentialLockers >= 0);
+
+ if (potentialLockers)
+ {
+ /* Already locked. Clean up and leave. */
+ EXIT_MONITOR (env, mcache.lockForPotentialLockersObj);
+ /* Ignore any error code from EXIT_MONITOR; there's nothing we could do
+ at this level, in any case. */
+ goto done;
+ }
+
+ /* Guaranteed not to block. */
+ if (ENTER_MONITOR (env, mcache.lockObj))
+ {
+ /* Clean up the existing lock. */
+ EXIT_MONITOR (env, mcache.lockForPotentialLockersObj);
+ /* Ignore any error code from EXIT_MONITOR; there's nothing we could do
+ at this level, in any case. */
+ goto done;
+ }
+
+
+ /* We have the monitor. Record that fact. */
+ potentialLockers = 1;
+ (*env)->SetIntField
+ (env, mutexObj, mutex_potentialLockers_fld, potentialLockers);
+ /* Set*Field() never fails */
+
+ ret = TRUE; /* We have the lock. */
+
+ /* Clean up. */
+ if (EXIT_MONITOR (env, mcache.lockForPotentialLockersObj))
+ goto done; /* If we fail at this point, still keep the
+ main lock. */
+
+ SHOW_OLD_TROUBLE ();
+done:
+ clean_mutexObj_cache (env, &mcache);
+ if (TRACE_API_CALLS)
+ tracing (" ==> %s\n", ret ? "TRUE" : "FALSE");
+ return ret;
}
+
/* Unlock a mutex. */
-static void g_mutex_unlock_jni_impl (GMutex *mutex) {
- JNIEnv *gdk_env;
+static void
+mutex_unlock_jni_impl (GMutex * gmutex)
+{
+ jobject mutexObj = (jobject) gmutex;
+ struct mutexObj_cache mcache;
+ JNIEnv *env;
+ union env_union e;
+
+ if (TRACE_API_CALLS)
+ tracing ("mutex_unlock_jni_impl(mutexObj=%p)", mutexObj);
+
+ e.jni_env = &env;
+ (*the_vm)->GetEnv (the_vm, e.void_env, JNI_VERSION_1_1);
+ if (setup_cache (env) < 0)
+ goto done;
+ HIDE_OLD_TROUBLE (env);
- (*gdk_vm)->GetEnv(gdk_vm, (void **)&gdk_env, JNI_VERSION_1_1);
+ assert (mutexObj);
- releaseLock(gdk_env, mutex);
+ if ( populate_mutexObj_cache (env, mutexObj, &mcache) < 0)
+ goto done;
+
+ (void) mutexObj_unlock (env, mutexObj, &mcache);
+
+ SHOW_OLD_TROUBLE ();
+
+done:
+ clean_mutexObj_cache (env, &mcache);
+ if (TRACE_API_CALLS)
+ tracing (" ==> VOID\n");
}
-/* Free a mutex (isn't C fun?) */
-static void g_mutex_free_jni_impl (GMutex *mutex)
+
+
+/* Free a mutex (isn't C fun?). OK this time for it to be NULL.
+ No failure conditions, for a change. */
+static void
+mutex_free_jni_impl (GMutex * mutex)
{
- freePlainObject( (jobject*)mutex );
+ jobject mutexObj = (jobject) mutex;
+ JNIEnv *env;
+ union env_union e;
+
+ e.jni_env = &env;
+ (*the_vm)->GetEnv (the_vm, e.void_env, JNI_VERSION_1_1);
+
+ if (TRACE_API_CALLS)
+ tracing ("mutex_free_jni_impl(%p)", mutexObj);
+
+ freeObject (env, mutexObj);
+
+ if (TRACE_API_CALLS)
+ tracing (" ==> VOID\n");
}
+
+
/************************************************************************/
/* Condition variable code */
/************************************************************************/
/* Create a new condition variable. This is a java.lang.Object for us. */
-static GCond *g_cond_new_jni_impl () {
- return (GCond*)allocatePlainObject();
+static GCond *
+cond_new_jni_impl (void)
+{
+ jobject condObj;
+ JNIEnv *env;
+ union env_union e;
+
+ if (TRACE_API_CALLS)
+ tracing ("mutex_free_jni_impl()");
+
+ e.jni_env = &env;
+ (*the_vm)->GetEnv (the_vm, e.void_env, JNI_VERSION_1_1);
+
+ condObj = allocatePlainObject (env);
+
+ if (TRACE_API_CALLS)
+ tracing (" ==> %p\n", condObj);
+
+ return (GCond *) condObj;
}
/* Signal on a condition variable. This is simply calling Object.notify
* for us.
*/
-static void g_cond_signal_jni_impl (GCond *cond) {
- jclass lcl_class;
- jmethodID signal_mth;
- JNIEnv *gdk_env;
+static void
+cond_signal_jni_impl (GCond * gcond)
+{
+ JNIEnv *env;
+ union env_union e;
+ jobject condObj = (jobject) gcond;
- (*gdk_vm)->GetEnv(gdk_vm, (void **)&gdk_env, JNI_VERSION_1_1);
+ if (TRACE_API_CALLS)
+ tracing ("cond_signal_jni_impl(condObj = %p)", condObj);
- lcl_class = (*gdk_env)->FindClass (gdk_env, "java.lang.Object");
- MAYBE_RETHROW(gdk_env, "cannot find Object");
-
- signal_mth = (*gdk_env)->GetMethodID(gdk_env, lcl_class, "notify", "()V");
- MAYBE_RETHROW(gdk_env, "cannot find Object.<notify>");
+ e.jni_env = &env;
+ (*the_vm)->GetEnv (the_vm, e.void_env, JNI_VERSION_1_1);
+ if (setup_cache (env) < 0)
+ goto done;
+ HIDE_OLD_TROUBLE (env);
+
+ assert (condObj);
/* Must have locked an object to call notify */
- takeLock(gdk_env, cond);
+ if (ENTER_MONITOR (env, condObj))
+ goto done;
+
+ (*env)->CallVoidMethod (env, condObj, obj_notify_mth);
+ if (MAYBE_BROKEN (env, "cannot signal mutex with Object.notify()"))
+ {
+ if (EXIT_MONITOR (env, condObj))
+ BADLY_BROKEN1 ("Failed to unlock a monitor; the VM may deadlock.");
+ goto done;
+ }
- (*gdk_env)->CallVoidMethod(gdk_env, *(jobject*)cond, signal_mth);
- MAYBE_RETHROW(gdk_env, "cannot signal mutex");
+ EXIT_MONITOR (env, condObj);
- releaseLock(gdk_env, cond);
+ SHOW_OLD_TROUBLE ();
+
+done:
+ if (TRACE_API_CALLS)
+ tracing (" ==> VOID\n");
}
/* Broadcast to all waiting on a condition variable. This is simply
* calling Object.notifyAll for us.
*/
-static void g_cond_broadcast_jni_impl (GCond *cond) {
- jclass lcl_class;
- jmethodID bcast_mth;
- JNIEnv *gdk_env;
+static void
+cond_broadcast_jni_impl (GCond * gcond)
+{
+ jobject condObj = (jobject) gcond;
+ JNIEnv *env;
+ union env_union e;
- (*gdk_vm)->GetEnv(gdk_vm, (void **)&gdk_env, JNI_VERSION_1_1);
+ if (TRACE_API_CALLS)
+ tracing ("cond_broadcast_jni_impl(condObj=%p)", condObj);
- lcl_class = (*gdk_env)->FindClass (gdk_env, "java.lang.Object");
- MAYBE_RETHROW(gdk_env, "cannot find Object");
-
- bcast_mth = (*gdk_env)->GetMethodID(gdk_env, lcl_class, "notifyAll", "()V");
- MAYBE_RETHROW(gdk_env, "cannot find Object.<notifyAll>");
+ e.jni_env = &env;
+ (*the_vm)->GetEnv (the_vm, e.void_env, JNI_VERSION_1_1);
+ if (setup_cache (env) < 0)
+ goto done;
+ HIDE_OLD_TROUBLE (env);
+ assert (condObj);
/* Must have locked an object to call notifyAll */
- takeLock(gdk_env, cond);
+ if (ENTER_MONITOR (env, condObj))
+ goto done;
+
+ (*env)->CallVoidMethod (env, condObj, obj_notifyall_mth);
+ if (MAYBE_BROKEN (env, "cannot broadcast to mutex with Object.notify()"))
+ {
+ EXIT_MONITOR (env, condObj);
+ goto done;
+ }
- (*gdk_env)->CallVoidMethod(gdk_env, *(jobject*)cond, bcast_mth);
- MAYBE_RETHROW(gdk_env, "cannot broadcast to mutex");
+ EXIT_MONITOR (env, condObj);
- releaseLock(gdk_env, cond);
+ SHOW_OLD_TROUBLE ();
+
+done:
+ if (TRACE_API_CALLS)
+ tracing (" ==> VOID\n");
}
-/* Wait on a condition variable. For us, this simply means call
+/* Wait on a condition variable. For us, this simply means calling
* Object.wait.
+ *
+ * Throws a Java exception on trouble; may leave the mutexes set arbitrarily.
+ * XXX TODO: Further improve error recovery.
*/
-static void g_cond_wait_jni_impl
- (GCond *cond, GMutex *mutex __attribute__((unused)))
+static void
+cond_wait_jni_impl (GCond * gcond, GMutex * gmutex)
{
- jclass lcl_class;
- jmethodID wait_mth;
- JNIEnv *gdk_env;
+ struct mutexObj_cache cache;
+ jobject condObj = (jobject) gcond;
+ jobject mutexObj = (jobject) gmutex;
+ JNIEnv *env;
+ union env_union e;
+
+ if (TRACE_API_CALLS)
+ tracing ("cond_wait_jni_impl(condObj=%p, mutexObj=%p)",
+ condObj, mutexObj);
+
+ e.jni_env = &env;
+ (*the_vm)->GetEnv (the_vm, e.void_env, JNI_VERSION_1_1);
+ if (setup_cache (env) < 0)
+ goto done;
+ HIDE_OLD_TROUBLE (env);
+
+ assert (condObj);
+ assert (mutexObj);
+ /* Must have locked a Java object to call wait on it */
+ if (ENTER_MONITOR (env, condObj) < 0)
+ goto done;
+
+ /* Our atomicity is now guaranteed; we're protected by the Java monitor on
+ condObj. Unlock the GMutex. */
+ if (mutexObj_unlock (env, mutexObj, &cache))
+ goto done;
+
+ (*env)->CallVoidMethod (env, condObj, obj_wait_mth);
+ if (MAYBE_BROKEN (env, "cannot wait on condObj"))
+ {
+ EXIT_MONITOR (env, condObj); /* ignore err checking */
+ goto done;
+ }
- (*gdk_vm)->GetEnv(gdk_vm, (void **)&gdk_env, JNI_VERSION_1_1);
+ /* Re-acquire the lock on the GMutex. Do this while we're protected by the
+ Java monitor on condObj. */
+ if (mutexObj_lock (env, mutexObj, &cache))
+ goto done;
- lcl_class = (*gdk_env)->FindClass (gdk_env, "java.lang.Object");
- MAYBE_RETHROW(gdk_env, "cannot find Object");
-
- wait_mth = (*gdk_env)->GetMethodID(gdk_env, lcl_class, "wait", "()V");
- MAYBE_RETHROW(gdk_env, "cannot find Object.<wait>");
+ EXIT_MONITOR (env, condObj);
- /* Must have locked an object to call wait */
- takeLock(gdk_env, cond);
+ SHOW_OLD_TROUBLE ();
- (*gdk_env)->CallVoidMethod(gdk_env, *(jobject*)cond, wait_mth);
- MAYBE_RETHROW(gdk_env, "cannot wait on mutex");
-
- releaseLock(gdk_env, cond);
+done:
+ if (TRACE_API_CALLS)
+ tracing (" ==> VOID\n");
}
-/* Wait on a condition vairable until a timeout. This is a little tricky
+
+/** Wait on a condition variable until a timeout. This is a little tricky
* for us. We first call Object.wait(J) giving it the appropriate timeout
* value. On return, we check whether an InterruptedException happened. If
- * so, that is Java-speak for wait timing out.
+ * so, that is Java-speak for wait timing out.
+ *
+ * We return FALSE if we timed out. Return TRUE if the condition was
+ * signalled first, before we timed out.
+ *
+ * In case of trouble we throw a Java exception. Whether we return FALSE or
+ * TRUE depends upon whether the condition was raised before the trouble
+ * happened.
+ *
+ * I believe that this function goes to the proper lengths to try to unlock
+ * all of the locked mutexes and monitors, as appropriate, and that it further
+ * tries to make sure that the thrown exception is the current one, not any
+ * future cascaded one from something like a failure to unlock the monitors.
*/
static gboolean
-g_cond_timed_wait_jni_impl
- (GCond *cond, GMutex *mutex __attribute__((unused)),
- GTimeVal *end_time)
+cond_timed_wait_jni_impl (GCond * gcond, GMutex * gmutex, GTimeVal * end_time)
{
- jclass lcl_class;
- jmethodID wait_mth;
- JNIEnv *gdk_env;
- jlong time;
+ JNIEnv *env;
+ union env_union e;
+ jlong time_millisec;
+ jint time_nanosec;
jthrowable cause;
+ jobject condObj = (jobject) gcond;
+ jobject mutexObj = (jobject) gmutex;
+ gboolean condRaised = FALSE; /* Condition has not been raised yet. */
+ struct mutexObj_cache cache;
+ gboolean interrupted;
+
+ if (TRACE_API_CALLS)
+ {
+ tracing ("cond_timed_wait_jni_impl(cond=%p, mutex=%p,"
+ " end_time=< sec=%lu, usec=%lu >)", condObj, mutexObj,
+ (unsigned long) end_time->tv_sec,
+ (unsigned long) end_time->tv_usec);
+ }
- (*gdk_vm)->GetEnv(gdk_vm, (void **)&gdk_env, JNI_VERSION_1_1);
- lcl_class = (*gdk_env)->FindClass (gdk_env, "java.lang.Object");
- MAYBE_RETHROW(gdk_env, "cannot find Object");
-
- wait_mth = (*gdk_env)->GetMethodID(gdk_env, lcl_class, "wait", "(J)V");
- MAYBE_RETHROW(gdk_env, "cannot find Object.<wait(J)>");
-
- time = end_time->tv_sec*1000;
- time += end_time->tv_usec/1000;
+ e.jni_env = &env;
+ (*the_vm)->GetEnv (the_vm, e.void_env, JNI_VERSION_1_1);
+ if (setup_cache (env) < 0)
+ goto done;
+ HIDE_OLD_TROUBLE (env);
+
+ time_millisec = end_time->tv_sec * 1000 + end_time->tv_usec / 1000;
+ time_nanosec = 1000 * (end_time->tv_usec % 1000);
/* Must have locked an object to call wait */
- takeLock(gdk_env, cond);
+ if (ENTER_MONITOR (env, condObj) < 0)
+ goto done;
+
+ if (mutexObj_unlock (env, mutexObj, &cache) < 0)
+ {
+ if (EXIT_MONITOR (env, condObj) < 0)
+ criticalMsg
+ ("Unable to unlock an existing lock on a condition; your proram may deadlock");
+ goto done;
+ }
+
+
+ (*env)->CallVoidMethod (env, condObj, obj_wait_nanotime_mth,
+ time_millisec, time_nanosec);
+
+ /* If there was trouble, save that fact, and the reason for the trouble. We
+ want to respond to this condition as fast as possible. */
+ cause = (*env)->ExceptionOccurred (env);
+
+ if ( ! cause )
+ {
+ condRaised = TRUE; /* condition was signalled */
+ }
+ else if ((*env)->IsInstanceOf (env, cause, interrupted_exception_class))
+ {
+ condRaised = FALSE; /* Condition was not raised before timeout.
+ (This is redundant with the initialization
+ of condRaised above) */
+ (*env)->ExceptionClear (env); /* Clear the InterruptedException. */
+ cause = NULL; /* no pending cause now. */
+ }
+ else
+ {
+ interrupted = FALSE; /* Trouble, but not because of
+ InterruptedException. Assume the condition
+ was not raised. */
+ /* Leave condRaised set to FALSE */
+ }
- (*gdk_env)->CallVoidMethod(gdk_env, *(jobject*)cond, wait_mth, time);
+ /* Irrespective of whether there is a pending problem to report, go ahead
+ and try to clean up. This may end up throwing an exception that is
+ different from the one that was thrown by the call to Object.wait().
+ So we will override it with the first exception (don't want to have
+ cascading problems). */
+ if (mutexObj_lock (env, mutexObj, &cache) && !cause)
+ {
+ cause = (*env)->ExceptionOccurred (env);
+ assert (cause);
+ }
- if ((cause = (*gdk_env)->ExceptionOccurred(gdk_env)) != NULL) {
- jclass intr = (*gdk_env)->FindClass (gdk_env, "java.lang.InterruptedException");
- if ( (*gdk_env)->IsInstanceOf(gdk_env, cause, intr) ) {
- releaseLock(gdk_env, cond);
- return FALSE;
- } else {
- MAYBE_RETHROW(gdk_env, "error in timed wait");
+ if (EXIT_MONITOR (env, condObj) && !cause)
+ {
+ cause = (*env)->ExceptionOccurred (env);
+ assert (cause);
}
- }
- releaseLock(gdk_env, cond);
+ if (cause) /* Raise the first cause. */
+ {
+ BROKEN_CAUSE (env, cause, "error in timed wait or during its cleanup");
+ goto done;
+ }
+
+ SHOW_OLD_TROUBLE ();
- return TRUE;
+done:
+ if (TRACE_API_CALLS)
+ tracing (" ==> condRaised = %s\n", condRaised ? "TRUE" : "FALSE");
+ return condRaised;
}
-/* Free a condition variable. (isn't C fun?) */
-static void g_cond_free_jni_impl (GCond *cond) {
- freePlainObject( (jobject*)cond );
+
+/* Free a condition variable. (isn't C fun?). Can not fail. */
+static void
+cond_free_jni_impl (GCond * cond)
+{
+ jobject condObj = (jobject) cond;
+ JNIEnv *env;
+ union env_union e;
+
+ if (TRACE_API_CALLS)
+ tracing ("cond_free_jni_impl(condObj = %p)", condObj);
+ e.jni_env = &env;
+ (*the_vm)->GetEnv (the_vm, e.void_env, JNI_VERSION_1_1);
+
+ freeObject (env, condObj);
+
+ if (TRACE_API_CALLS)
+ tracing (" ==> VOID\n");
}
@@ -380,128 +1955,638 @@ static void g_cond_free_jni_impl (GCond *cond) {
/* Thread-local data code */
/************************************************************************/
-/* Create a new thread-local key. We use java.lang.ThreadLocal objects
- * for this.
+/* Create a new thread-local key. We use java.lang.ThreadLocal objects
+ * for this. This returns the pointer representation of a Java global
+ * reference.
+ *
+ * We will throw a Java exception and return NULL in case of failure.
*/
-static GPrivate *g_private_new_jni_impl
- (GDestroyNotify notify __attribute__((unused)))
+static GPrivate *
+private_new_jni_impl (GDestroyNotify notify __attribute__ ((unused)))
{
- jclass lcl_class;
- jobject *local;
- JNIEnv *gdk_env;
- jmethodID ctor;
+ JNIEnv *env;
+ union env_union e;
+ jobject lcl_key;
+ jobject global_key;
+ GPrivate *gkey = NULL; /* Error return code */
+
+ if (TRACE_API_CALLS)
+ tracing ("private_new_jni_impl()");
+
+ e.jni_env = &env;
+ (*the_vm)->GetEnv (the_vm, e.void_env, JNI_VERSION_1_1);
+ if (setup_cache (env) < 0)
+ goto done;
+ HIDE_OLD_TROUBLE (env);
+
+ lcl_key = (*env)->NewObject (env, threadlocal_class, threadlocal_ctor);
+ if ( ! lcl_key )
+ {
+ BROKEN (env, "cannot allocate a ThreadLocal");
+ goto done;
+ }
- (*gdk_vm)->GetEnv(gdk_vm, (void **)&gdk_env, JNI_VERSION_1_1);
+ global_key = ((*env)->NewGlobalRef (env, lcl_key));
+ DELETE_LOCAL_REF (env, lcl_key);
+ if ( ! global_key)
+ {
+ NEW_BROKEN (env, "cannot create a GlobalRef to a new ThreadLocal");
+ goto done;
+ }
- lcl_class = (*gdk_env)->FindClass (gdk_env, "java.lang.ThreadLocal");
- MAYBE_RETHROW(gdk_env, "cannot find ThreadLocal");
+ gkey = (GPrivate *) global_key;
+ SHOW_OLD_TROUBLE ();
- ctor = (*gdk_env)->GetMethodID(gdk_env, lcl_class, "<init>", "()V");
- MAYBE_RETHROW(gdk_env, "cannot find ThreadLocal.<init>");
+done:
+ if (TRACE_API_CALLS)
+ tracing (" ==> %p\n", (void *) gkey);
- local = (jobject *) g_malloc (sizeof (jobject));
- *local = (*gdk_env)->NewObject(gdk_env, lcl_class, ctor);
- MAYBE_RETHROW(gdk_env, "cannot allocate a ThreadLocal");
-
- *local = ((*gdk_env)->NewGlobalRef (gdk_env, *local));
- MAYBE_RETHROW(gdk_env, "cannot create a GlobalRef");
-
- return (GPrivate*) local;
+ return gkey;
}
/* Get this thread's value for a thread-local key. This is simply
- * ThreadLocal.get for us.
+ * ThreadLocal.get for us. Return NULL if no value. (I can't think of
+ * anything else to do.)
*/
-static gpointer g_private_get_jni_impl (GPrivate *private) {
- jclass lcl_class;
- jobject lcl_obj;
- JNIEnv *gdk_env;
- jmethodID get_mth;
- jclass int_class;
- jmethodID val_mth;
- jint int_val;
-
- (*gdk_vm)->GetEnv(gdk_vm, (void **)&gdk_env, JNI_VERSION_1_1);
+static gpointer
+private_get_jni_impl (GPrivate * gkey)
+{
+ JNIEnv *env;
+ union env_union e;
+ jobject val_wrapper;
+ jobject keyObj = (jobject) gkey;
+ gpointer thread_specific_data = NULL; /* Init to the error-return value */
+
+ jlong val;
+
+ if (TRACE_API_CALLS)
+ tracing ("private_get_jni_impl(keyObj=%p)", keyObj);
+
+ e.jni_env = &env;
+ (*the_vm)->GetEnv (the_vm, e.void_env, JNI_VERSION_1_1);
+ if (setup_cache (env) < 0)
+ goto done;
+ HIDE_OLD_TROUBLE (env);
+
+ val_wrapper = (*env)->CallObjectMethod (env, keyObj, threadlocal_get_mth);
+ if (MAYBE_BROKEN (env, "cannot find thread-local object"))
+ goto done;
+
+ if (! val_wrapper )
+ {
+ /* It's Java's "null" object. No ref found. This is OK; we must never
+ have set a value in this thread. Note that this next statement is
+ not necessary, strictly speaking, since we're already initialized to
+ NULL. A good optimizing C compiler will detect that and optimize out
+ this statement. */
+ thread_specific_data = NULL;
+ goto done;
+ }
- lcl_class = (*gdk_env)->FindClass (gdk_env, "java.lang.ThreadLocal");
- MAYBE_RETHROW(gdk_env, "cannot find ThreadLocal");
+ val = (*env)->CallLongMethod (env, val_wrapper, long_longValue_mth);
- get_mth = (*gdk_env)->GetMethodID(gdk_env, lcl_class, "get", "()Ljava/lang/Object;");
- MAYBE_RETHROW(gdk_env, "cannot find ThreadLocal.<get>");
+ if (MAYBE_BROKEN (env, "cannot get thread local value"))
+ goto done;
- lcl_obj = (*gdk_env)->CallObjectMethod(gdk_env, *(jobject*)private, get_mth);
- MAYBE_RETHROW(gdk_env, "cannot find thread-local object");
+ thread_specific_data = (gpointer) (intptr_t) val;
- int_class = (*gdk_env)->FindClass (gdk_env, "java.lang.Integer");
- MAYBE_RETHROW(gdk_env, "cannot find Integer");
+ /* Only re-raise the old pending exception if a new one hasn't come along to
+ supersede it. */
+ SHOW_OLD_TROUBLE ();
- val_mth = (*gdk_env)->GetMethodID(gdk_env, int_class, "intValue", "()I");
- MAYBE_RETHROW(gdk_env, "cannot find Integer.<intValue>");
+done:
- int_val = (*gdk_env)->CallIntMethod(gdk_env, lcl_obj, val_mth);
- MAYBE_RETHROW(gdk_env, "cannot get thread local value");
+ if (TRACE_API_CALLS)
+ tracing (" ==> %p\n", thread_specific_data);
- return (gpointer) int_val;
+ return thread_specific_data;
}
-/* Set this thread's value for a thread-local key. This is simply
- * ThreadLocal.set for us.
+/* Set this thread's value for a thread-local key. This is simply
+ * ThreadLocal.set() for us.
*/
-static void g_private_set_jni_impl (GPrivate *private, gpointer data) {
- jclass lcl_class, int_class;
- jobject lcl_obj;
- JNIEnv *gdk_env;
- jmethodID new_int, set_mth;
+static void
+private_set_jni_impl (GPrivate * gkey, gpointer thread_specific_data)
+{
+ JNIEnv *env;
+ union env_union e;
+ jobject val_wrapper;
+ jobject keyObj = (jobject) gkey;
+
+
+ if (TRACE_API_CALLS)
+ tracing ("private_set_jni_impl(keyObj=%p, thread_specific_data=%p)",
+ keyObj, thread_specific_data);
+
+ e.jni_env = &env;
+ (*the_vm)->GetEnv (the_vm, e.void_env, JNI_VERSION_1_1);
+ if (setup_cache (env) < 0)
+ goto done;
+ HIDE_OLD_TROUBLE (env);
+
+ /* We are just going to always use a Java long to represent a C pointer.
+ Otherwise all of the code would end up being conditionalized for various
+ pointer sizes, and that seems like too much of a hassle, in order to save
+ a paltry few bytes, especially given the horrendous overhead of JNI in
+ any case.
+ */
+
+ val_wrapper = (*env)->NewObject (env, long_class, long_ctor,
+ (jlong) (intptr_t) thread_specific_data);
+ if ( ! val_wrapper )
+ {
+ BROKEN (env, "cannot create a java.lang.Long");
+ goto done;
+ }
+
+ /* At this point, we now have set lcl_obj as a numeric class that wraps
+ around the thread-specific data we were given. */
+ (*env)->CallVoidMethod (env, keyObj, threadlocal_set_mth, val_wrapper);
+ if (MAYBE_BROKEN (env, "cannot set thread local value"))
+ goto done;
+
+ SHOW_OLD_TROUBLE ();
+done:
+ if (TRACE_API_CALLS)
+ tracing (" ==> VOID\n");
+}
+
+
+/** Create an object of type gnu.java.awt.peer.gtk.GThreadNativeMethodRunner.
+ Run it.
+
+ We need to create joinable threads. We handle the notion of a joinable
+ thread by determining whether or not we are going to maintain a permanent
+ hard reference to it until it croaks.
+
+ Posix does not appear to have a Java-like concept of daemon threads, where
+ the JVM will exit when there are only daemon threads running.
+
+ Error handling:
+
+ To quote from the glib guide:
+ "GError should only be used to report recoverable runtime errors, never
+ to report programming errors."
+
+ So how do we consider the failure to create a thread? Well, each of the
+ failure cases in this function are discussed, and none of them are really
+ recoverable.
+
+ The glib library is really designed so that you should fail
+ catastrophically in case of "programming errors". The only error defined
+ for the GThread functions is G_THREAD_ERROR_AGAIN, and that for
+ thread_create.
+
+ Most of these GThread functions could fail if we run out of memory, for
+ example, but the only one capable of reporting that fact is
+ thread_create. */
+static void
+thread_create_jni_impl (GThreadFunc func,
+ gpointer data,
+ gulong stack_size __attribute__((unused)),
+ gboolean joinable,
+ gboolean bound __attribute__((unused)),
+ GThreadPriority gpriority,
+ /* This prototype is horrible. threadIDp is actually
+ a gpointer to the thread's thread-ID. Which is,
+ of course, itself a gpointer-typed value. Ouch. */
+ gpointer threadIDp,
+ /* Do not touch the GError stuff unless you have
+ RECOVERABLE trouble. There is no recoverable
+ trouble in this implementation. */
+ GError **errorp __attribute__((unused)))
+{
+ JNIEnv *env;
+ union env_union e;
+ union func_union f;
+ jboolean jjoinable = joinable;
+ jobject newThreadObj;
+ gpointer threadID; /* to be filled in */
+
+ if (TRACE_API_CALLS)
+ {
+ f.g_func = func;
+ tracing ("thread_create_jni_impl(func=%p, data=%p, joinable=%s,"
+ " threadIDp=%p, *(int *) threadIDp = %d)",
+ f.void_func, data, joinable ? "TRUE" : "FALSE",
+ threadIDp, *(int *) threadIDp);
+ }
+
+ e.jni_env = &env;
+ (*the_vm)->GetEnv (the_vm, e.void_env, JNI_VERSION_1_1);
+ if (setup_cache (env) < 0)
+ {
+ /* The failed call to setup the cache is certainly not recoverable;
+ not appropriate for G_THREAD_ERROR_AGAIN. */
+ *(gpointer *) threadIDp = NULL;
+ goto done;
+ }
+ HIDE_OLD_TROUBLE (env);
+
+ /* If a thread is joinable, then notify its constructor. The constructor
+ will enter a hard reference for it, and the hard ref. won't go away until
+ the thread has been joined. */
+ newThreadObj =
+ (*env)->NewObject (env, runner_class, runner_ctor,
+ (jlong) (intptr_t) func, (jlong) (intptr_t) data,
+ jjoinable);
+ if ( ! newThreadObj )
+ {
+ BROKEN (env, "creating a new thread failed in the constructor");
+ *(gpointer *) threadIDp = NULL;
+ /* The failed call to the constructor does not throw any errors such
+ that G_THREAD_ERROR_AGAIN is appropriate. No other recoverable
+ errors defined. Once again, we go back to the VM. */
+ goto done;
+ }
+
+ if (threadObj_set_priority (env, newThreadObj, gpriority) < 0)
+ {
+ *(gpointer *) threadIDp = NULL;
+ /* None of these possible exceptions from Thread.setPriority() are
+ recoverable, so they are not appropriate for EAGAIN. So we should
+ fail. */
+ goto done;
+ }
+
+ (*env)->CallVoidMethod (env, runner_class, runner_start_mth);
+
+ if (MAYBE_BROKEN (env, "starting a new thread failed"))
+ {
+ *(gpointer *) threadIDp = NULL;
+ /* The only exception Thread.start() throws is
+ IllegalStateException. And that would indicate a programming error.
+
+ So there are no situations such that G_THREAD_ERROR_AGAIN would be
+ OK.
+
+ So, we don't use g_set_error() here to perform any error reporting.
+ */
+ goto done;
+ }
+
+ threadID = getThreadIDFromThread (env, newThreadObj);
+
+ *(gpointer *) threadIDp = threadID;
+ SHOW_OLD_TROUBLE ();
+
+done:
+ if (TRACE_API_CALLS)
+ tracing (" ==> (threadID = %p) \n", threadID);
+}
+
+
+/* Wraps a call to g_thread_yield. */
+static void
+thread_yield_jni_impl (void)
+{
+ JNIEnv *env;
+ union env_union e;
+
+ if (TRACE_API_CALLS)
+ tracing ("thread_yield_jni_impl()");
+
+ e.jni_env = &env;
+ (*the_vm)->GetEnv (the_vm, e.void_env, JNI_VERSION_1_1);
+ if (setup_cache (env) < 0)
+ goto done;
+ HIDE_OLD_TROUBLE (env);
+
+ (*env)->CallStaticVoidMethod (env, thread_class, thread_yield_mth);
+ if (MAYBE_BROKEN (env, "Thread.yield() failed"))
+ goto done;
+
+ SHOW_OLD_TROUBLE ();
+
+done:
+ if (TRACE_API_CALLS)
+ tracing (" ==> VOID\n");
+}
+
+
+static void
+thread_join_jni_impl (gpointer threadID)
+{
+ JNIEnv *env;
+ union env_union e;
+ jobject threadObj = NULL;
+
+ if ( TRACE_API_CALLS )
+ tracing ("thread_join_jni_impl(threadID=%p) ", threadID);
+
+ e.jni_env = &env;
+ (*the_vm)->GetEnv (the_vm, e.void_env, JNI_VERSION_1_1);
+ if (setup_cache (env) < 0)
+ goto done;
+ HIDE_OLD_TROUBLE (env);
+
+ threadObj = getThreadFromThreadID (env, threadID);
+ if ( ! threadObj ) /* Already reported with BROKEN */
+ goto done;
+
+ (*env)->CallVoidMethod (env, threadObj, thread_join_mth);
+ if (MAYBE_BROKEN (env, "Thread.join() failed"))
+ goto done;
+
+
+ (*env)->CallStaticVoidMethod
+ (env, runner_class, runner_deRegisterJoinable_mth, threadObj);
+ if (MAYBE_BROKEN (env, "Thread.deRegisterJoinableThread() failed"))
+ goto done;
+
+ SHOW_OLD_TROUBLE ();
+
+done:
+ DELETE_LOCAL_REF (env, threadObj);
+ if (TRACE_API_CALLS)
+ tracing (" ==> VOID \n");
+}
+
+/* Terminate the current thread. Unlike pthread_exit(), here we do not need
+ to bother with a return value or exit value for the thread which is about
+ to croak. (The gthreads abstraction doesn't use it.) However, we *do*
+ need to bail immediately. We handle this with Thread.stop(), which is
+ a deprecated method.
+
+ It's deprecated since we might leave objects protected by monitors in
+ half-constructed states on the way out -- Thread.stop() throws a
+ ThreadDeath exception, which is usually unchecked. There is no good
+ solution that I can see. */
+static void
+thread_exit_jni_impl (void)
+{
+ JNIEnv *env;
+ union env_union e;
+ jobject this_thread;
+
+ if (TRACE_API_CALLS)
+ tracing ("thread_exit_jni_impl() ");
+
+ e.jni_env = &env;
+ (*the_vm)->GetEnv (the_vm, e.void_env, JNI_VERSION_1_1);
+ if (setup_cache (env) < 0)
+ goto done;
+
+ HIDE_OLD_TROUBLE (env);
+
+ this_thread = (*env)->
+ CallStaticObjectMethod (env, thread_class, thread_current_mth);
+
+ if ( ! this_thread )
+ {
+ BROKEN (env, "cannot get current thread");
+ goto done;
+ }
+
+ (*env)->CallVoidMethod (env, this_thread, thread_stop_mth);
+ if (MAYBE_BROKEN (env, "cannot call Thread.stop() on current thread"))
+ goto done;
+
+ SHOW_OLD_TROUBLE ();
+
+done:
+ if (TRACE_API_CALLS)
+ tracing (" ==> VOID \n");
+}
+
+
+/* Translate a GThreadPriority to a Java priority level. */
+static jint
+javaPriorityLevel (GThreadPriority priority)
+{
+ /* We have these fields in java.lang.Thread to play with:
+
+ static int MIN_PRIORITY The minimum priority that a thread can have.
+ static int NORM_PRIORITY The default priority that is assigned to a
+ thread.
+ static int MAX_PRIORITY The maximum priority that a thread can have.
+
+ We get these from the header file generated by javah, even though they're
+ documented as being 1, 5, and 10.
+ */
+ static const jint minJPri =
+ gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_MIN_PRIORITY;
+ static const jint normJPri =
+ gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_NORM_PRIORITY;
+ static const jint maxJPri =
+ gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_MAX_PRIORITY;
+
+ switch (priority)
+ {
+ case G_THREAD_PRIORITY_LOW:
+ return minJPri;
+ break;
+
+ default:
+ assert_not_reached ();
+ /* Deliberate fall-through if assertions are turned off; also shuts up
+ GCC warnings if they're turned on. */
+ case G_THREAD_PRIORITY_NORMAL:
+ return normJPri;
+ break;
+
+ case G_THREAD_PRIORITY_HIGH:
+ return (normJPri + maxJPri) / 2;
+ break;
+
+ case G_THREAD_PRIORITY_URGENT:
+ return maxJPri;
+ break;
+ }
+}
+
+
+/** It would be safe not to implement this, according to the JNI docs, since
+ not all platforms do thread priorities. However, we might as well
+ provide the hint for those who want it.
+*/
+static void
+thread_set_priority_jni_impl (gpointer gThreadID, GThreadPriority gpriority)
+{
+ jobject threadObj = NULL;
+ JNIEnv *env;
+ union env_union e;
+
+ if (TRACE_API_CALLS)
+ tracing ("thread_set_priority_jni_impl(gThreadID=%p, gpriority = %u) ",
+ gThreadID, gpriority);
+
+ e.jni_env = &env;
+ (*the_vm)->GetEnv (the_vm, e.void_env, JNI_VERSION_1_1);
+
+ if (setup_cache (env) < 0)
+ goto done;
+
+ HIDE_OLD_TROUBLE (env);
+
+
+ threadObj = getThreadFromThreadID (env, gThreadID);
+ if ( ! threadObj) /* Reported with BROKEN already. */
+ goto done;
+
+ if (threadObj_set_priority (env, threadObj, gpriority))
+ goto done;
+
+ SHOW_OLD_TROUBLE ();
+
+done:
+ DELETE_LOCAL_REF (env, threadObj);
+
+ if (TRACE_API_CALLS)
+ tracing (" ==> VOID\n");
+}
+
+
+/** It would be safe not to implement this, according to the JNI docs, since
+ not all platforms do thread priorities. However, we might as well
+ provide the hint for those who want it.
+
+ -1 on failure, 0 on success. */
+static int
+threadObj_set_priority (JNIEnv * env, jobject threadObj,
+ GThreadPriority gpriority)
+{
+ jint javaPriority = javaPriorityLevel (gpriority);
+ (*env)->CallVoidMethod (env, threadObj, thread_setPriority_mth,
+ javaPriority);
+ return MAYBE_BROKEN (env, "Thread.setPriority() failed");
+}
- (*gdk_vm)->GetEnv(gdk_vm, (void **)&gdk_env, JNI_VERSION_1_1);
- int_class = (*gdk_env)->FindClass (gdk_env, "java.lang.Integer");
- MAYBE_RETHROW(gdk_env, "cannot find Integer");
+/** Return the result of Thread.currentThread(), a static method. */
+static void
+thread_self_jni_impl (/* Another confusing glib prototype. This is
+ actually a gpointer to the thread's thread-ID.
+ Which is, of course, a gpointer. */
+ gpointer my_thread_IDp)
+{
+ JNIEnv *env;
+ union env_union e;
+ jobject this_thread;
+ gpointer my_threadID;
- new_int = (*gdk_env)->GetMethodID(gdk_env, int_class, "<init>", "(I)V");
- MAYBE_RETHROW(gdk_env, "cannot find Integer.<init>");
+ if (TRACE_API_CALLS)
+ tracing ("thread_self_jni_impl(my_thread_IDp=%p)", my_thread_IDp);
- lcl_obj = (*gdk_env)->NewObject(gdk_env, int_class, new_int, (jint)data);
- MAYBE_RETHROW(gdk_env, "cannot create an Integer");
+ e.jni_env = &env;
+ (*the_vm)->GetEnv (the_vm, e.void_env, JNI_VERSION_1_1);
- lcl_class = (*gdk_env)->FindClass (gdk_env, "java.lang.ThreadLocal");
- MAYBE_RETHROW(gdk_env, "cannot find ThreadLocal");
+ if (setup_cache (env) < 0)
+ return;
- set_mth = (*gdk_env)->GetMethodID(gdk_env, lcl_class, "set", "(Ljava/lang/Object;)V");
- MAYBE_RETHROW(gdk_env, "cannot find ThreadLocal.<set>");
+ HIDE_OLD_TROUBLE (env);
- (*gdk_env)->CallVoidMethod(gdk_env, *(jobject*)private, set_mth, lcl_obj);
- MAYBE_RETHROW(gdk_env, "cannot set thread local value");
+ this_thread = (*env)->
+ CallStaticObjectMethod (env, thread_class, thread_current_mth);
+ if (! this_thread )
+ {
+ BROKEN (env, "cannot get current thread");
+ my_threadID = NULL;
+ goto done;
+ }
+
+ my_threadID = getThreadIDFromThread (env, this_thread);
+ SHOW_OLD_TROUBLE ();
+
+done:
+ if (TRACE_API_CALLS)
+ tracing (" ==> (my_threadID = %p) \n", my_threadID);
+
+ *(gpointer *) my_thread_IDp = my_threadID;
}
+static gboolean
+thread_equal_jni_impl (gpointer thread1, gpointer thread2)
+{
+ JNIEnv *env;
+ union env_union e;
+
+ gpointer threadID1 = *(gpointer *) thread1;
+ gpointer threadID2 = *(gpointer *) thread2;
+
+ jobject thread1_obj = NULL;
+ jobject thread2_obj = NULL;
+ gboolean ret;
+
+ if (TRACE_API_CALLS)
+ tracing ("thread_equal_jni_impl(threadID1=%p, threadID2=%p)",
+ threadID1, threadID2);
+
+ e.jni_env = &env;
+ (*the_vm)->GetEnv (the_vm, e.void_env, JNI_VERSION_1_1);
+ if (setup_cache (env) < 0)
+ {
+ ret = FALSE; /* what is safer? We really don't ever want
+ to return from here. */
+ goto done;
+ }
+
+ HIDE_OLD_TROUBLE (env);
+ thread1_obj = getThreadFromThreadID (env, threadID1);
+ thread2_obj = getThreadFromThreadID (env, threadID2);
+
+ ret = (*env)->CallBooleanMethod (env, thread1_obj,
+ thread_equals_mth, thread2_obj);
+
+ if (MAYBE_BROKEN (env, "Thread.equals() failed"))
+ {
+ ret = FALSE;
+ goto done;
+ }
+
+ SHOW_OLD_TROUBLE ();
+
+
+done:
+ DELETE_LOCAL_REF (env, thread1_obj);
+ DELETE_LOCAL_REF (env, thread2_obj);
+
+ if (TRACE_API_CALLS)
+ tracing (" ==> %s\n", ret ? "TRUE" : "FALSE");
+
+ return ret;
+}
+
+
+
+
/************************************************************************/
/* GLIB interface */
/************************************************************************/
/* set of function pointers to give to glib. */
-GThreadFunctions g_thread_jni_functions =
-{
- g_mutex_new_jni_impl, /* mutex_new */
- g_mutex_lock_jni_impl, /* mutex_lock */
- g_mutex_trylock_jni_impl, /* mutex_try_lock */
- g_mutex_unlock_jni_impl, /* mutex_unlock */
- g_mutex_free_jni_impl, /* mutex_free */
- g_cond_new_jni_impl, /* cond_new */
- g_cond_signal_jni_impl, /* cond_signal */
- g_cond_broadcast_jni_impl, /* cond_broadcast */
- g_cond_wait_jni_impl, /* cond_wait */
- g_cond_timed_wait_jni_impl, /* cond_timed_wait */
- g_cond_free_jni_impl, /* cond_free */
- g_private_new_jni_impl, /* private_new */
- g_private_get_jni_impl, /* private_get */
- g_private_set_jni_impl, /* private_set */
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
+GThreadFunctions portable_native_sync_jni_functions = {
+ mutex_new_jni_impl, /* mutex_new */
+ mutex_lock_jni_impl, /* mutex_lock */
+ mutex_trylock_jni_impl, /* mutex_trylock */
+ mutex_unlock_jni_impl, /* mutex_unlock */
+ mutex_free_jni_impl, /* mutex_free */
+ cond_new_jni_impl, /* cond_new */
+ cond_signal_jni_impl, /* cond_signal */
+ cond_broadcast_jni_impl, /* cond_broadcast */
+ cond_wait_jni_impl, /* cond_wait */
+ cond_timed_wait_jni_impl, /* cond_timed_wait */
+ cond_free_jni_impl, /* cond_free */
+ private_new_jni_impl, /* private_new */
+ private_get_jni_impl, /* private_get */
+ private_set_jni_impl, /* private_set */
+ thread_create_jni_impl, /* thread_create */
+ thread_yield_jni_impl, /* thread_yield */
+ thread_join_jni_impl, /* thread_join */
+ thread_exit_jni_impl, /* thread_exit */
+ thread_set_priority_jni_impl, /* thread_set_priority */
+ thread_self_jni_impl, /* thread_self */
+ thread_equal_jni_impl, /* thread_equal */
};
-
+
+
+/* Keep c-font-lock-extra-types in alphabetical order. */
+/* Local Variables: */
+/* c-file-style: "gnu" */
+/* c-font-lock-extra-types: ("\\sw+_t" "gboolean" "GError" "gpointer"
+ "GPrivate" "GThreadFunc" "GThreadFunctions" "GThreadPriority"
+ "gulong"
+ "JNIEnv"
+ "jboolean" "jclass" "jfieldID" "jint" "jlong" "jmethodID" "jobject" "jstring" "jthrowable" ) */
+/* End: */
diff --git a/libjava/jni/gtk-peer/gthread-jni.h b/libjava/jni/gtk-peer/gthread-jni.h
index a0d093dccc8..90a252fa5c0 100644
--- a/libjava/jni/gtk-peer/gthread-jni.h
+++ b/libjava/jni/gtk-peer/gthread-jni.h
@@ -42,7 +42,7 @@ exception statement from your version. */
#include <glib.h>
#include "gtkpeer.h"
-extern GThreadFunctions g_thread_jni_functions;
-extern JavaVM *gdk_vm;
+extern GThreadFunctions portable_native_sync_jni_functions;
+extern JavaVM *the_vm;
#endif /* __GTHREADJNI_H__ */
diff --git a/libjava/jni/gtk-peer/gtkpeer.h b/libjava/jni/gtk-peer/gtkpeer.h
index 18c95102472..59d49cedadc 100644
--- a/libjava/jni/gtk-peer/gtkpeer.h
+++ b/libjava/jni/gtk-peer/gtkpeer.h
@@ -91,6 +91,20 @@ extern struct state_table *native_global_ref_table;
(*env)->DeleteGlobalRef (env, *globRefPtr); \
free (globRefPtr);} while (0)
+extern struct state_table *native_pixbufdecoder_state_table;
+
+#define NSA_PB_INIT(env, clazz) \
+ native_pixbufdecoder_state_table = init_state_table (env, clazz)
+
+#define NSA_GET_PB_PTR(env, obj) \
+ get_state (env, obj, native_pixbufdecoder_state_table)
+
+#define NSA_SET_PB_PTR(env, obj, ptr) \
+ set_state (env, obj, native_pixbufdecoder_state_table, (void *)ptr)
+
+#define NSA_DEL_PB_PTR(env, obj) \
+ remove_state_slot (env, obj, native_pixbufdecoder_state_table)
+
#endif /* JVM_SUN */
struct graphics
@@ -118,14 +132,14 @@ struct graphics
#define SYNTHETIC_EVENT_MASK (1 << 10)
-#define AWT_SHIFT_MASK (1 << 0)
-#define AWT_CTRL_MASK (1 << 1)
-#define AWT_META_MASK (1 << 2)
-#define AWT_ALT_MASK (1 << 3)
+#define AWT_SHIFT_DOWN_MASK (1 << 6)
+#define AWT_CTRL_DOWN_MASK (1 << 7)
+#define AWT_META_DOWN_MASK (1 << 8)
+#define AWT_ALT_DOWN_MASK (1 << 9)
-#define AWT_BUTTON1_MASK (1 << 4)
-#define AWT_BUTTON2_MASK AWT_ALT_MASK
-#define AWT_BUTTON3_MASK AWT_META_MASK
+#define AWT_BUTTON1_DOWN_MASK (1 << 10)
+#define AWT_BUTTON2_DOWN_MASK (1 << 11)
+#define AWT_BUTTON3_DOWN_MASK (1 << 12)
#define MULTI_CLICK_TIME 250
/* as opposed to a MULTI_PASS_TIME :) */
@@ -459,4 +473,19 @@ struct item_event_hook_info
const char *label;
};
+#define DEBUG_LOCKING 0
+
+#if DEBUG_LOCKING
+#define gdk_threads_enter() \
+{ \
+ g_print ("lock: %s, %d\n", __FILE__, __LINE__); \
+ gdk_threads_enter (); \
+}
+#define gdk_threads_leave() \
+{ \
+ g_print ("unlock: %s, %d\n", __FILE__, __LINE__); \
+ gdk_threads_leave (); \
+}
+#endif
+
#endif /* __GTKPEER_H */