summaryrefslogtreecommitdiff
path: root/rgfw.c3l
diff options
context:
space:
mode:
Diffstat (limited to 'rgfw.c3l')
-rw-r--r--rgfw.c3l/LICENSE674
-rw-r--r--rgfw.c3l/include/RGFW.h5081
-rw-r--r--rgfw.c3l/manifest.json10
-rw-r--r--rgfw.c3l/rgfw.c3760
4 files changed, 4249 insertions, 2276 deletions
diff --git a/rgfw.c3l/LICENSE b/rgfw.c3l/LICENSE
new file mode 100644
index 0000000..f288702
--- /dev/null
+++ b/rgfw.c3l/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<https://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<https://www.gnu.org/licenses/why-not-lgpl.html>.
diff --git a/rgfw.c3l/include/RGFW.h b/rgfw.c3l/include/RGFW.h
index 8016f02..844eb95 100644
--- a/rgfw.c3l/include/RGFW.h
+++ b/rgfw.c3l/include/RGFW.h
@@ -41,8 +41,8 @@
#define RGFW_X11 (optional) (unix only) if X11 should be used. This option is turned on by default by unix systems except for MacOS
#define RGFW_WAYLAND (optional) (unix only) use Wayland. (This can be used with X11)
+ #define RGFW_NO_STATIC_CONTEXT - do not initalizize with a static variable, use the heap if RGFW is not manually initalized
#define RGFW_NO_X11 (optional) (unix only) don't fallback to X11 when using Wayland
- #define RGFW_NO_LOAD_WGL (optional) (windows only) if WGL should be loaded dynamically during runtime
#define RGFW_NO_X11_CURSOR (optional) (unix only) don't use XCursor
#define RGFW_NO_X11_CURSOR_PRELOAD (optional) (unix only) use XCursor, but don't link it in code, (you'll have to link it with -lXcursor)
#define RGFW_NO_X11_EXT_PRELOAD (optional) (unix only) use Xext, but don't link it in code, (you'll have to link it with -lXext)
@@ -55,10 +55,11 @@
#define RGFW_COCOA_GRAPHICS_SWITCHING - (optional) (cocoa) use automatic graphics switching (allow the system to choose to use GPU or iGPU)
#define RGFW_COCOA_FRAME_NAME (optional) (cocoa) set frame name
#define RGFW_NO_DPI - do not calculate DPI and don't use libShcore (win32)
- #define RGFW_NO_XRANDR - do use not XRandr (X11)
#define RGFW_ADVANCED_SMOOTH_RESIZE - use advanced methods for smooth resizing (may result in a spike in memory usage or worse performance) (eg. WM_TIMER and XSyncValue)
#define RGFW_NO_INFO - do not define the RGFW_info struct (without RGFW_IMPLEMENTATION)
#define RGFW_NO_GLXWINDOW - do not use GLXWindow
+ #define RGFW_NO_ALLOCATE_MONITORS - do not allocate monitors on the heap at all (when there's no pre-allocated space left)
+ #define RGFW_NO_INCLUDE_VULKAN - do not include the Vulkan.h header, you have to include it yourself
#define RGFW_ALLOC x - choose the default allocation function (defaults to standard malloc)
#define RGFW_FREE x - choose the default deallocation function (defaults to standard free)
@@ -69,12 +70,14 @@
#define RGFW_USE_INT - force the use c-types rather than stdint.h (for systems that might not have stdint.h (msvc))
#define RGFW_bool x - choose what type to use for bool, by default u32 is used
+
+ #define RGFW_PREALLOCATED_MONITORS x - choose the default amount of pre-allocated monitors (can be zero)
*/
/*
Example to get you started :
-linux : gcc main.c -lX11 -lXrandr -lm
+*nix : gcc main.c -lX11 -lXrandr -lm
windows : gcc main.c -lgdi32
macos : gcc main.c -framework Cocoa -framework CoreVideo -framework IOKit
@@ -116,7 +119,7 @@ int main() {
shared :
windows:
gcc -shared RGFW.o -lopengl32 -lgdi32 -o RGFW.dll
- linux:
+ unix:
gcc -shared RGFW.o -lX11 -lGL -lXrandr -o RGFW.so
macos:
gcc -shared RGFW.o -framework CoreVideo -framework Cocoa -framework OpenGL -framework IOKit
@@ -165,7 +168,7 @@ int main() {
#pragma comment(lib, "User32")
#pragma comment(lib, "Advapi32")
#pragma warning( push )
- #pragma warning( disable : 4995 4191 4127)
+ #pragma warning( disable : 4996 4191 4127)
#if _MSC_VER < 600
#define RGFW_C89
#endif
@@ -175,15 +178,14 @@ int main() {
#endif
#endif
-#if defined(RGFW_EGL) && !defined(RGFW_OPENGL)
- #define RGFW_OPENGL
-#endif
-
/* these OS macros look better & are standardized */
/* plus it helps with cross-compiling */
#ifdef __EMSCRIPTEN__
#define RGFW_WASM
+ #ifdef RGFW_EGL
+ #define RGFW_OPENGL
+ #endif
#endif
#if defined(RGFW_X11) && defined(__APPLE__) && !defined(RGFW_CUSTOM_BACKEND)
@@ -212,11 +214,27 @@ int main() {
#define RGFW_MACOS
#endif
+#if defined(RGFW_X11) || defined(RGFW_WASM) || defined(RGFW_WAYLAND)
+ #ifndef _POSIX_C_SOURCE
+ #define _POSIX_C_SOURCE 199309L
+ #endif
+
+ /* __USE_POSIX199309 is part of glibc internals, and isn't intended to be used outside. */
+ /* However, existing RGFW code may depend on it implicitly. */
+ #ifndef __USE_POSIX199309
+ #define __USE_POSIX199309
+ #endif
+#endif
+
#ifndef RGFW_ASSERT
#include <assert.h>
#define RGFW_ASSERT assert
#endif
+#ifndef RGFW_STATIC_ASSERT
+ #define RGFW_STATIC_ASSERT(check_name, x) typedef char RGFW_check_##check_name[(x) ? 1 : -1];
+#endif
+
#if !defined(__STDC_VERSION__)
#define RGFW_C89
#endif
@@ -239,6 +257,10 @@ int main() {
#define RGFW_ROUND(x) (i32)((x) >= 0 ? (x) + 0.5f : (x) - 0.5f)
#endif
+#ifndef RGFW_ABS
+ #define RGFW_ABS(x) (((x) < 0) ? -(x) : (x))
+#endif
+
#ifndef RGFW_ROUNDF
#define RGFW_ROUNDF(x) (float)((i32)((x) + ((x) < 0.0f ? -0.5f : 0.5f)))
#endif
@@ -293,9 +315,10 @@ int main() {
#ifndef RGFW_MAX_EVENTS
#define RGFW_MAX_EVENTS 32
#endif
-
-#ifndef RGFW_MAX_MONITORS
- #define RGFW_MAX_MONITORS 6
+#ifndef RGFW_PREALLOCATED_MONITORS
+ #define RGFW_PREALLOCATED_MONITORS 6 /* the number of preallocated monitors */
+#elif defined(RGFW_NO_ALLOCATE_MONITORS) && (RGFW_PREALLOCATED_MONITORS == 0)
+ #warning RGFW monitors have no place to be allocated
#endif
#ifndef RGFW_COCOA_FRAME_NAME
@@ -345,16 +368,28 @@ int main() {
#define RGFW_HEADER
#include <stddef.h>
+#include <limits.h>
+
#ifndef RGFW_INT_DEFINED
#ifdef RGFW_USE_INT /* optional for any system that might not have stdint.h */
typedef unsigned char u8;
typedef signed char i8;
typedef unsigned short u16;
typedef signed short i16;
- typedef unsigned long int u32;
- typedef signed long int i32;
- typedef unsigned long long u64;
- typedef signed long long i64;
+ #if INT_MAX == 0x7FFFFFFF
+ typedef unsigned int u32;
+ typedef signed int i32;
+ #else
+ typedef unsigned long int u32;
+ typedef signed long int i32;
+ #endif
+ #if LONG_MAX == 0x7FFFFFFFFFFFFFFFL
+ typedef unsigned long u64;
+ typedef signed long i64;
+ #else
+ typedef unsigned long long u64;
+ typedef signed long long i64;
+ #endif
#else /* use stdint standard types instead of c "standard" types */
#include <stdint.h>
@@ -370,7 +405,9 @@ int main() {
#define RGFW_INT_DEFINED
#endif
-typedef ptrdiff_t RGFW_ssize_t;
+RGFW_STATIC_ASSERT(size64, sizeof(i64) == 8)
+RGFW_STATIC_ASSERT(size32, sizeof(i32) == 4)
+RGFW_STATIC_ASSERT(size16, sizeof(i16) == 2)
#ifndef RGFW_BOOL_DEFINED
#define RGFW_BOOL_DEFINED
@@ -381,7 +418,7 @@ typedef ptrdiff_t RGFW_ssize_t;
#define RGFW_TRUE (RGFW_bool)1
#define RGFW_FALSE (RGFW_bool)0
-#define RGFW_ENUM(type, name) type name; enum
+#define RGFW_ENUM(type, name) type name; enum name##_enum
#define RGFW_BIT(x) (1 << (x))
#ifdef RGFW_VULKAN
@@ -408,8 +445,31 @@ typedef ptrdiff_t RGFW_ssize_t;
#define RGFW_VK_SURFACE NULL
#endif
+ #ifndef RGFW_NO_INCLUDE_VULKAN
+ #include <vulkan/vulkan.h>
+ #endif
+
+ #if defined(RGFW_X11)
+ typedef VkResult (VKAPI_PTR *RGFW_vkCreateXlibSurfaceKHRProc)(VkInstance, const VkXlibSurfaceCreateInfoKHR*, const VkAllocationCallbacks*, VkSurfaceKHR*);
+ typedef VkBool32 (VKAPI_PTR *RGFW_vkGetPhysicalDeviceXlibPresentationSupportKHRProc)(VkPhysicalDevice, uint32_t, Display*, VisualID);
+ #endif
+ #ifdef RGFW_WAYLAND
+ typedef VkResult (VKAPI_PTR *RGFW_vkCreateWaylandSurfaceKHRProc)(VkInstance, const VkWaylandSurfaceCreateInfoKHR*, const VkAllocationCallbacks*, VkSurfaceKHR*);
+ typedef VkBool32 (VKAPI_PTR *RGFW_vkGetPhysicalDeviceWaylandPresentationSupportKHRProc)(VkPhysicalDevice, uint32_t, struct wl_display*);
+ #endif
+ #ifdef RGFW_WINDOWS
+ typedef VkResult (VKAPI_PTR *RGFW_vkCreateWin32SurfaceKHRProc)(VkInstance, const VkWin32SurfaceCreateInfoKHR*, const VkAllocationCallbacks*, VkSurfaceKHR*);
+ typedef VkBool32 (VKAPI_PTR *RGFW_vkGetPhysicalDeviceWin32PresentationSupportKHRProc)(VkPhysicalDevice, uint32_t);
+ #endif
#endif
+/*! @brief Flags for RGFW initialization */
+typedef RGFW_ENUM(u8, RGFW_initFlags) {
+ RGFW_initOpenGL = RGFW_BIT(0), /*!< Load Native OpenGL */
+ RGFW_initEGL = RGFW_BIT(1), /*!< Load EGL */
+ RGFW_initVulkan = RGFW_BIT(2), /*!< Load Vulkan */
+ RGFW_initX11 = RGFW_BIT(3) /*!< Force X11 (over Wayland) */
+};
/*! @brief The stucture that contains information about the current RGFW instance */
typedef struct RGFW_info RGFW_info;
@@ -616,9 +676,9 @@ typedef RGFW_ENUM(u8, RGFW_key) {
/*! @brief abstract mouse button codes */
typedef RGFW_ENUM(u8, RGFW_mouseButton) {
- RGFW_mouseLeft = 0, /*!< left mouse button is pressed */
- RGFW_mouseMiddle, /*!< mouse-wheel-button is pressed */
- RGFW_mouseRight, /*!< right mouse button is pressed */
+ RGFW_mouseLeft = 0, /*!< left mouse button */
+ RGFW_mouseMiddle, /*!< mouse-wheel-button */
+ RGFW_mouseRight, /*!< right mouse button */
RGFW_mouseMisc1, RGFW_mouseMisc2, RGFW_mouseMisc3, RGFW_mouseMisc4, RGFW_mouseMisc5,
RGFW_mouseFinal
};
@@ -639,7 +699,7 @@ typedef RGFW_ENUM(u8, RGFW_dndActionType) {
RGFW_dndActionNone = 0,
RGFW_dndActionEnter, /*!< data has been dragged into the window area */
RGFW_dndActionMove, /*!< the data that was dragged into the window area has moved inside the window */
- RGFW_dndActionExit, /*!< the data that was dragged into the window area has left the window */
+ RGFW_dndActionExit /*!< the data that was dragged into the window area has left the window */
};
/*! types of transfered data (clipboard, dnd) */
@@ -652,10 +712,17 @@ typedef RGFW_ENUM(u8, RGFW_dataTransferType) {
RGFW_dataUnknown /*!< unknown raw data */
};
+/*! struct for data transfers, mostly used for the clipboard API */
+typedef struct RGFW_dataTransfer {
+ const char* data; /*!< transfered data */
+ size_t length; /*!< the full length of the data in bytes, including null-terminator, if included. null-terminators are ensured when reading data from RGFW */
+ RGFW_dataTransferType type; /*!< the type of data being transfered */
+} RGFW_dataTransfer;
+
/*! internal node for a individual data drop */
typedef struct RGFW_dataDropNode {
const char* data; /*!< dropped data */
- size_t size; /*!< the size of the data in bytes */
+ size_t length; /*!< the size of the data in bytes */
RGFW_dataTransferType type; /*!< the type of data being dropped */
struct RGFW_dataDropNode* next; /*!< the next drop data node if any [when handling callbacks, this will always be NULL because the linked list is built as events are processed] */
} RGFW_dataDropNode;
@@ -669,7 +736,7 @@ typedef RGFW_ENUM(u8, RGFW_eventType) {
RGFW_mouseButtonPressed, /*!< a mouse button has been pressed (left,middle,right) */
RGFW_mouseButtonReleased, /*!< a mouse button has been released (left,middle,right) */
RGFW_mouseScroll, /*!< a mouse scroll event */
- RGFW_mousePosChanged, /*!< the position of the mouse has been changed */
+ RGFW_mouseMotion, /*!< the position of the mouse has been changed / the mouse has moved */
RGFW_mouseRawMotion, /*!< raw mouse motion */
RGFW_mouseEnter, /*!< mouse entered the window */
RGFW_mouseLeave, /*!< mouse left the window */
@@ -687,7 +754,8 @@ typedef RGFW_ENUM(u8, RGFW_eventType) {
RGFW_scaleUpdated, /*!< content scale factor changed */
RGFW_monitorConnected, /*!< a monitor has been connected */
RGFW_monitorDisconnected, /*!< a monitor has been disconnected */
- RGFW_eventCount /*!< the number of event types there are */
+ RGFW_eventCount, /*!< the number of event types there are */
+ RGFW_mousePosChanged = RGFW_mouseMotion /*!< alias for RGFW_mouseMotion (may be deleted at some point) */
};
/*! @brief flags for toggling whether or not an event should be processed */
@@ -698,7 +766,7 @@ typedef RGFW_ENUM(u32, RGFW_eventFlag) {
RGFW_mouseScrollFlag = RGFW_BIT(RGFW_mouseScroll),
RGFW_mouseButtonPressedFlag = RGFW_BIT(RGFW_mouseButtonPressed),
RGFW_mouseButtonReleasedFlag = RGFW_BIT(RGFW_mouseButtonReleased),
- RGFW_mousePosChangedFlag = RGFW_BIT(RGFW_mousePosChanged),
+ RGFW_mouseMotionFlag = RGFW_BIT(RGFW_mouseMotion),
RGFW_mouseRawMotionFlag = RGFW_BIT(RGFW_mouseRawMotion),
RGFW_mouseEnterFlag = RGFW_BIT(RGFW_mouseEnter),
RGFW_mouseLeaveFlag = RGFW_BIT(RGFW_mouseLeave),
@@ -716,9 +784,10 @@ typedef RGFW_ENUM(u32, RGFW_eventFlag) {
RGFW_dataDragFlag = RGFW_BIT(RGFW_dataDrag),
RGFW_monitorConnectedFlag = RGFW_BIT(RGFW_monitorConnected),
RGFW_monitorDisconnectedFlag = RGFW_BIT(RGFW_monitorDisconnected),
+ RGFW_mousePosChangedFlag = RGFW_mouseMotionFlag, /* alias for RGFW_mouseMotionFlag (may be deleted at some point) */
RGFW_keyEventsFlag = RGFW_keyPressedFlag | RGFW_keyReleasedFlag | RGFW_keyCharFlag,
- RGFW_mouseEventsFlag = RGFW_mouseButtonPressedFlag | RGFW_mouseButtonReleasedFlag | RGFW_mousePosChangedFlag | RGFW_mouseEnterFlag | RGFW_mouseLeaveFlag | RGFW_mouseScrollFlag | RGFW_mouseRawMotionFlag,
+ RGFW_mouseEventsFlag = RGFW_mouseButtonPressedFlag | RGFW_mouseButtonReleasedFlag | RGFW_mouseMotionFlag | RGFW_mouseEnterFlag | RGFW_mouseLeaveFlag | RGFW_mouseScrollFlag | RGFW_mouseRawMotionFlag,
RGFW_windowEventsFlag = RGFW_windowMovedFlag | RGFW_windowResizedFlag | RGFW_windowRefreshFlag | RGFW_windowMaximizedFlag | RGFW_windowMinimizedFlag | RGFW_windowRestoredFlag | RGFW_scaleUpdatedFlag,
RGFW_windowFocusEventsFlag = RGFW_windowFocusInFlag | RGFW_windowFocusOutFlag,
RGFW_dataDragDropEventsFlag = RGFW_dataDropFlag | RGFW_dataDragFlag,
@@ -756,13 +825,13 @@ typedef struct RGFW_mouseDeltaEvent {
float x, y; /*!< the raw mouse scroll or motion delta value */
} RGFW_mouseDeltaEvent;
-/*! @brief event data for a mouse position event (RGFW_mousePosChanged) */
-typedef struct RGFW_mousePosEvent {
+/*! @brief event data for a mouse position event (RGFW_mouseMotion) */
+typedef struct RGFW_mouseMotionEvent {
RGFW_eventType type; /*!< which event has been sent?*/
RGFW_window* win; /*!< the window this event applies to (for event queue events) */
i32 x, y; /*!< mouse x, y of event (or drop point) */
RGFW_bool inWindow; /*!< if the mouse is in the window or not */
-} RGFW_mousePosEvent;
+} RGFW_mouseMotionEvent;
/*! @brief event data for a key press/release event */
typedef struct RGFW_keyEvent {
@@ -830,7 +899,7 @@ typedef union RGFW_event {
RGFW_windowUpdateEvent update; /*!< data for window update/move/resize/refresh events */
RGFW_mouseButtonEvent button; /*!< data for a button press/release */
RGFW_mouseDeltaEvent delta; /*!< data for a mouse scroll or raw motion */
- RGFW_mousePosEvent mouse; /*!< data for mouse motion events */
+ RGFW_mouseMotionEvent mouse; /*!< data for mouse motion events */
RGFW_keyEvent key; /*!< data for key press/release/hold events */
RGFW_keyCharEvent keyChar; /*!< data for key character events */
RGFW_dataDropEvent drop; /*!< data dropping events */
@@ -859,13 +928,24 @@ typedef struct RGFW_callbacks {
RGFW_genericFunc arr[RGFW_eventCount]; /*!< an array of all the callbacks */
} RGFW_callbacks;
+typedef RGFW_ENUM(u8, RGFW_fullscreenMode) {
+ RGFW_fullscreenNone,
+ /*!< borderless/windowed fullscreen | the window changes it's size to match the monitor's current mode
+ the window is not hidden and maintains it's size when it is unfocused */
+ RGFW_fullscreenBorderless, /*!< borderless/windowed fullscreen */
+ /*!< exclusive fullscreen | the monitor's mode tries to change to match the window's size.
+ The original mode is toggled when the window goes in and out of focus and
+ the window is hidden when it is not in focus */
+ RGFW_fullscreenExclusive, /*!< exclusive fullscreen */
+};
+
/*! @brief optional bitwise arguments for making a windows, these can be OR'd together */
typedef RGFW_ENUM(u32, RGFW_windowFlags) {
RGFW_windowNoBorder = RGFW_BIT(0), /*!< the window doesn't have a border / frame / decor */
RGFW_windowNoResize = RGFW_BIT(1), /*!< the window cannot be resized by the user */
RGFW_windowAllowDND = RGFW_BIT(2), /*!< the window supports drag and drop */
RGFW_windowHideMouse = RGFW_BIT(3), /*! the window should hide the mouse (can be toggled later on using `RGFW_window_showMouse`) */
- RGFW_windowFullscreen = RGFW_BIT(4), /*!< the window is fullscreen by default */
+ RGFW_windowFullscreenExclusive = RGFW_BIT(4), /*!< the window is exclusive fullscreen by default */
RGFW_windowTranslucent = RGFW_BIT(5), /*!< the window is translucent (only properly works on X11 and MacOS, although it's meant for for windows) */
RGFW_windowTransparent = RGFW_windowTranslucent, /*!< the window is translucent (only properly works on X11 and MacOS, although it's meant for for windows) */
RGFW_windowCenter = RGFW_BIT(6), /*! center the window on the screen */
@@ -881,8 +961,7 @@ typedef RGFW_ENUM(u32, RGFW_windowFlags) {
RGFW_windowCaptureMouse = RGFW_BIT(16), /*!< capture the mouse mouse mouse on window creation */
RGFW_windowOpenGL = RGFW_BIT(17), /*!< create an OpenGL context (you can also do this manually with RGFW_window_createContext_OpenGL) */
RGFW_windowEGL = RGFW_BIT(18), /*!< create an EGL context (you can also do this manually with RGFW_window_createContext_EGL) */
- RGFW_noDeinitOnClose = RGFW_BIT(19), /*!< do not auto deinit RGFW if the window closes and this is the last window open */
- RGFW_windowedFullscreen = RGFW_windowNoBorder | RGFW_windowMaximize,
+ RGFW_windowFullscreenBorderless = RGFW_BIT(19), /*!< the window is borderless fullscreen by default */
RGFW_windowCaptureRawMouse = RGFW_windowCaptureMouse | RGFW_windowRawMouse
};
@@ -945,8 +1024,10 @@ typedef RGFW_ENUM(u8, RGFW_errorCode) {
RGFW_errFailedFuncLoad,
RGFW_errBuffer,
RGFW_errMetal,
+ RGFW_errObjcRuntime,
RGFW_errPlatform,
RGFW_errEventQueue,
+ RGFW_errNoInit,
RGFW_infoWindow, RGFW_infoBuffer, RGFW_infoGlobal, RGFW_infoOpenGL,
RGFW_warningWayland, RGFW_warningOpenGL
};
@@ -964,7 +1045,7 @@ typedef void (* RGFW_debugFunc)(const RGFW_debugInfo* info);
/*! @brief function pointer equivalent of void* */
typedef void (*RGFW_proc)(void);
-#if defined(RGFW_OPENGL)
+#if defined(RGFW_OPENGL) || defined(RGFW_EGL)
/*! @brief abstract structure for interfacing with the underlying OpenGL API */
typedef struct RGFW_glContext RGFW_glContext;
@@ -983,7 +1064,8 @@ typedef RGFW_ENUM(i32, RGFW_glProfile) {
RGFW_glCore = 0, /*!< the core OpenGL version, e.g. just support for that version */
RGFW_glForwardCompatibility, /*!< only compatibility for newer versions of OpenGL as well as the requested version */
RGFW_glCompatibility, /*!< allow compatibility for older versions of OpenGL as well as the requested version */
- RGFW_glES /*!< use OpenGL ES */
+ RGFW_glES, /*!< use OpenGL ES */
+ RGFW_glWeb /*!< use WebGL version (otherwise the version is changed to match it's GLES equivalent) */
};
/*! values for the renderer hint */
@@ -1014,7 +1096,7 @@ typedef struct RGFW_glHints {
RGFW_glRenderer renderer; /*!< renderer to use e.g. accelerated or software defaults to accelerated */
} RGFW_glHints;
-#endif
+#endif /* RGFW_OPENGL */
/**!
* @brief Allocates memory using the allocator defined by RGFW_ALLOC at compile time.
@@ -1030,6 +1112,51 @@ RGFWDEF void* RGFW_alloc(size_t size);
RGFWDEF void RGFW_free(void* ptr);
/**!
+ * @brief Retrieves the size of the RGFW_info structure.
+ * @return The size (in bytes) of RGFW_info.
+*/
+RGFWDEF size_t RGFW_sizeofInfo(void);
+
+/**!
+ * @brief Initializes the RGFW library internally.
+ * @param className The class name for the application.
+ * @param flags The initialization flags.
+ * @return 0 on success, a negative number error error on failure and a positive number for a warning.
+*/
+RGFWDEF i32 RGFW_init(const char* className, RGFW_initFlags flags);
+
+/**!
+ * @brief Deinitializes the current instance of the RGFW library.
+*/
+RGFWDEF void RGFW_deinit(void);
+
+/**!
+ * @brief Initializes RGFW using a user-provided RGFW_info structure.
+ * @param info A pointer to an RGFW_info structure to be used for initialization.
+ * @return 0 on success, a negative number error error on failure and a positive number for a warning.
+*/
+RGFWDEF i32 RGFW_init_ptr(const char* className, RGFW_initFlags flags, RGFW_info* info);
+
+/**!
+ * @brief Deinitializes a specific RGFW instance stored in the provided RGFW_info pointer.
+ * @param info A pointer to the RGFW_info structure representing the instance to deinitialize.
+*/
+RGFWDEF void RGFW_deinit_ptr(RGFW_info* info);
+
+/**!
+ * @brief Sets the global RGFW_info structure pointer.
+ * @param info A pointer to the RGFW_info structure to set.
+*/
+RGFWDEF void RGFW_setInfo(RGFW_info* info);
+
+/**!
+ * @brief Retrieves the global RGFW_info structure pointer.
+ * @return A pointer to the current RGFW_info structure.
+*/
+RGFWDEF RGFW_info* RGFW_getInfo(void);
+
+
+/**!
* @brief Returns the size (in bytes) of the RGFW_window structure.
* @return The size of the RGFW_window structure.
*/
@@ -1042,15 +1169,6 @@ RGFWDEF size_t RGFW_sizeofWindow(void);
RGFWDEF size_t RGFW_sizeofWindowSrc(void);
/**!
- * @brief (Unix) Toggles the use of Wayland.
- * This is enabled by default when compiled with `RGFW_WAYLAND`.
- * If not using `RGFW_WAYLAND`, Wayland functions are not exposed.
- * This function can be used to force the use of XWayland.
- * @param wayland A boolean value indicating whether to use Wayland (true) or not (false).
-*/
-RGFWDEF void RGFW_useWayland(RGFW_bool wayland);
-
-/**!
* @brief Checks if Wayland is currently being used.
* @return RGFW_TRUE if using Wayland, RGFW_FALSE otherwise.
*/
@@ -1075,21 +1193,6 @@ RGFWDEF void* RGFW_getDisplay_X11(void);
RGFWDEF struct wl_display* RGFW_getDisplay_Wayland(void);
/**!
- * @brief Sets the class name for X11 and WinAPI windows.
- * Windows with the same class name will be grouped by the window manager.
- * By default, the class name matches the root window’s name.
- * @param name The class name to assign.
-*/
-RGFWDEF void RGFW_setClassName(const char* name);
-
-/**!
- * @brief Sets the X11 instance name.
- * By default, the window name will be used as the instance name.
- * @param name The X11 instance name to set.
-*/
-RGFWDEF void RGFW_setXInstName(const char* name);
-
-/**!
* @brief (macOS only) Changes the current working directory to the application’s resource folder.
*/
RGFWDEF void RGFW_moveToMacOSResourceDir(void);
@@ -1336,13 +1439,27 @@ RGFWDEF RGFW_bool RGFW_monitor_getMode(RGFW_monitor* monitor, RGFW_monitorMode*
RGFWDEF void RGFW_pollMonitors(void);
/**!
- * @brief Retrieves an array of all available monitors.
- * @param len [OUTPUT] A pointer to store the number of monitors found (maximum of RGFW_MAX_MONITORS [6 by default]).
- * @return An array of pointers to RGFW_monitor structures.
+ * @brief free all leftlover monitor data (this is called internally RGFW_deinit)
+*/
+RGFWDEF void RGFW_freeMonitors(void);
+
+/**!
+ * @brief Allocates and returns an array of all available monitors.
+ * @param len [OUTPUT] A pointer to store the number of monitors found.
+ * @return An allocated array of pointers to RGFW_monitor structures that must be freed.
*/
RGFWDEF RGFW_monitor** RGFW_getMonitors(size_t* len);
/**!
+ * @brief fills a pre-allocated array with available monitors.
+ * @param maximum number of monitors that the passed [monitors] buffer supports, can be zero to get the length alone
+ * @param pre-allocated buffer of monitors, can be NULL to get the length alone
+ * @param len [OUTPUT] A pointer to store the number of monitors found, if max is not zero and monitors is not NULL, length will be set to max.
+ * @return An array of pointers to RGFW_monitor structures or NULL if the function failed.
+*/
+RGFWDEF RGFW_bool RGFW_getMonitorsPtr(size_t max, RGFW_monitor** monitors, size_t* len);
+
+/**!
* @brief Retrieves the primary monitor.
* @return A pointer to the RGFW_monitor structure representing the primary monitor.
*/
@@ -1538,7 +1655,7 @@ RGFWDEF void RGFW_getMouseVector(float* x, float* y);
*
* NOTE: (windows) if the executable has an icon resource named RGFW_ICON, it will be set as the initial icon for the window
*/
-RGFWDEF RGFW_window* RGFW_createWindow(const char* name, i32 x, i32 y, i32 w, i32 h, RGFW_windowFlags flags);
+RGFWDEF RGFW_window* RGFW_createWindow(const char* name, i32 x, i32 y, i32 w, i32 h, RGFW_windowFlags flags);
/**!
* @brief creates a new window using a pre-allocated window structure
@@ -1864,7 +1981,7 @@ RGFWDEF RGFW_bool RGFW_window_getDataDrag(RGFW_window* win, i32* x, i32* y);
RGFWDEF RGFW_bool RGFW_window_didDataDrop(RGFW_window* win);
/**!
- * @brief retrieves datta from a data drop (drag and drop)
+ * @brief retrieves data from a data drop (drag and drop)
* @param win a pointer to the target window
* @return a valid pointer to the root drag node if a data drop occurred, NULL otherwise
*/
@@ -1966,9 +2083,9 @@ RGFWDEF void RGFW_window_maximize(RGFW_window* win);
/**!
* @brief toggles fullscreen mode for the window
* @param win a pointer to the target window
- * @param fullscreen RGFW_TRUE to enable fullscreen, RGFW_FALSE to disable
+ * @param fullscreen the fullscreen mode to use RGFW_fullscreenNone, RGFW_fullscreenBorderless, RGFW_fullscreenExclusive
*/
-RGFWDEF void RGFW_window_setFullscreen(RGFW_window* win, RGFW_bool fullscreen);
+RGFWDEF void RGFW_window_setFullscreen(RGFW_window* win, RGFW_fullscreenMode mode);
/**!
* @brief centers the window on the screen
@@ -2208,13 +2325,27 @@ RGFWDEF void RGFW_window_moveMouse(RGFW_window* win, i32 x, i32 y);
RGFWDEF RGFW_bool RGFW_window_shouldClose(RGFW_window* win);
/**!
- * @brief Checks if the window is currently fullscreen.
+ * @brief Checks if the window is currently fullscreen (borderless or exclusive).
* @param win The target window.
* @return True if the window is fullscreen.
*/
RGFWDEF RGFW_bool RGFW_window_isFullscreen(RGFW_window* win);
/**!
+ * @brief Checks if the window is currently fullscreen (exclusive).
+ * @param win The target window.
+ * @return True if the window is fullscreen.
+*/
+RGFWDEF RGFW_bool RGFW_window_isFullscreenExclusive(RGFW_window* win);
+
+/**!
+ * @brief Checks if the window is currently fullscreen (borderless).
+ * @param win The target window.
+ * @return True if the window is fullscreen.
+*/
+RGFWDEF RGFW_bool RGFW_window_isFullscreenBorderless(RGFW_window* win);
+
+/**!
* @brief Checks if the window is currently hidden.
* @param win The target window.
* @return True if the window is hidden.
@@ -2269,25 +2400,43 @@ RGFWDEF RGFW_monitor* RGFW_window_getMonitor(RGFW_window* win);
/**!
* @brief Reads clipboard data.
- * @param size [OUTPUT] A pointer that will be filled with the size of the clipboard data.
- * @return A pointer to the clipboard data as a string.
+ * @param requestedType the requested clipboard data type to attempt to read
+ * @return A pointer to the clipboard data object or NULL on failure.
+*/
+RGFWDEF const RGFW_dataTransfer* RGFW_readClipboard(RGFW_dataTransferType requestedType);
+
+/**!
+ * @brief Reads clipboard data into your object pointer using your provided buffer, or returns the required length if the buffer is NULL or bufferCapacity is 0.
+ * @param requestedType the requested clipboard data type to attempt to read
+ * @param buffer the buffer used to fill the output dataTransfer object's data
+ * @param capacity the capacity/length of the buffer in bytes
+ * @param data [OUTPUT] A pointer to the dataTransfer object that will receive the clipboard data. (cannot be NULL)
+ * @return returns RGFW_TRUE on success and RGFW_FALSE on failure
*/
-RGFWDEF const char* RGFW_readClipboard(size_t* size);
+RGFWDEF RGFW_bool RGFW_readClipboardPtr(RGFW_dataTransferType requestedType, u8* buffer, size_t capacity, RGFW_dataTransfer* data);
/**!
- * @brief Reads clipboard data into a provided buffer, or returns the required length if str is NULL.
- * @param str [OUTPUT] A pointer to the buffer that will receive the clipboard data (or NULL to get required size).
- * @param strCapacity The capacity of the provided buffer.
- * @return The number of bytes read or required length of clipboard data.
+ * @brief Reads clipboard string data.
+ * @param requestedType the requested clipboard data type to attempt to read
+ * @return A pointer to the clipboard data object or NULL on failure.
*/
-RGFWDEF RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity);
+RGFWDEF const RGFW_dataTransfer* RGFW_readClipboardString(void);
/**!
- * @brief Writes text to the clipboard.
- * @param text The text to be written to the clipboard.
- * @param textLen The length of the text being written.
+ * @brief Reads clipboard data into your object pointer using your provided buffer, or returns the required length if the buffer is NULL or bufferCapacity is 0.
+ * @param buffer the buffer used to fill the output dataTransfer object's data
+ * @param capacity the capacity/length of the buffer in bytes
+ * @param data [OUTPUT] A pointer to the dataTransfer object that will receive the clipboard data. (cannot be NULL)
+ * @return returns RGFW_TRUE on success and RGFW_FALSE on failure
*/
-RGFWDEF void RGFW_writeClipboard(const char* text, u32 textLen);
+RGFWDEF RGFW_bool RGFW_readClipboardStringPtr(u8* buffer, size_t capacity, RGFW_dataTransfer* data);
+
+/**!
+ * @brief Writes data to the clipboard.
+ * @param data The data to be written to the clipboard, including the length and type.
+ * @param returns RGFW_TRUE on success and RGFW_FALSE on failure
+*/
+RGFWDEF RGFW_bool RGFW_writeClipboard(const RGFW_dataTransfer* data);
/** @} */
@@ -2313,17 +2462,8 @@ RGFWDEF void RGFW_debugCallback(RGFW_debugType type, RGFW_errorCode code, const
/** * @defgroup graphics_API
* @{ */
-/*! native rendering API functions */
-#if defined(RGFW_OPENGL)
-/* these are native opengl specific functions and will NOT work with EGL */
-
-/*!< make the window the current OpenGL drawing context
-
- NOTE:
- if you want to switch the graphics context's thread,
- you have to run RGFW_window_makeCurrentContext_OpenGL(NULL); on the old thread
- then RGFW_window_makeCurrentContext_OpenGL(valid_window) on the new thread
-*/
+#if defined(RGFW_OPENGL) || defined(RGFW_EGL)
+/* these are generic functions that work for both EGL and native OpenGL */
/**!
* @brief Sets the global OpenGL hints to the specified pointer.
@@ -2342,47 +2482,85 @@ RGFWDEF void RGFW_resetGlobalHints_OpenGL(void);
*/
RGFWDEF RGFW_glHints* RGFW_getGlobalHints_OpenGL(void);
+#endif
+
+/*! native rendering API functions */
+#if defined(RGFW_OPENGL)
+/* these are native opengl specific functions and will NOT work with EGL */
+
+/*!< make the window the current OpenGL drawing context
+
+ NOTE:
+ if you want to switch the graphics context's thread,
+ you have to run RGFW_window_makeCurrentContext_OpenGL(NULL); on the old thread
+ then RGFW_window_makeCurrentContext_OpenGL(valid_window) on the new thread
+*/
+
/**!
- * @brief Creates and allocates an OpenGL context for the specified window.
- * @param win A pointer to the target RGFW_window.
+ * @brief Creates and allocates an OpenGL context that can be attached to a window.
* @param hints A pointer to an RGFW_glHints structure defining context creation parameters.
* @return A pointer to the newly created RGFW_glContext.
*/
-RGFWDEF RGFW_glContext* RGFW_window_createContext_OpenGL(RGFW_window* win, RGFW_glHints* hints);
+RGFWDEF RGFW_glContext* RGFW_createContext_OpenGL(RGFW_glHints* hints);
/**!
- * @brief Creates an OpenGL context for the specified window using a preallocated context structure.
- * @param win A pointer to the target RGFW_window.
+ * @brief Creates an OpenGL context that can be attached to a window, using a preallocated context structure.
* @param ctx A pointer to an already allocated RGFW_glContext structure.
* @param hints A pointer to an RGFW_glHints structure defining context creation parameters.
* @return RGFW_TRUE on success, RGFW_FALSE on failure.
*/
-RGFWDEF RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx, RGFW_glHints* hints);
-
-/**!
- * @brief Retrieves the OpenGL context associated with a window.
- * @param win A pointer to the RGFW_window.
- * @return A pointer to the associated RGFW_glContext, or NULL if none exists or if the context is EGL-based.
-*/
-RGFWDEF RGFW_glContext* RGFW_window_getContext_OpenGL(RGFW_window* win);
+RGFWDEF RGFW_bool RGFW_createContextPtr_OpenGL(RGFW_glContext* ctx, RGFW_glHints* hints);
/**!
* @brief Deletes and frees the OpenGL context.
- * @param win A pointer to the RGFW_window.
* @param ctx A pointer to the RGFW_glContext to delete.
*
+ * @note Only use this version if you allocated a context with RGFW_createContext_OpenGL
* @note This is automatically called by RGFW_window_close if the window’s context is not NULL.
+ * @note you should set the window context to NULL with RGFW_window_setContext_OpenGL(win, NULL) after calling this function
*/
-RGFWDEF void RGFW_window_deleteContext_OpenGL(RGFW_window* win, RGFW_glContext* ctx);
+RGFWDEF void RGFW_deleteContext_OpenGL(RGFW_glContext* ctx);
/**!
* @brief Deletes the OpenGL context without freeing its memory.
* @param win A pointer to the RGFW_window.
* @param ctx A pointer to the RGFW_glContext to delete.
*
+ * @note Only use this version if you allocated a context with RGFW_createContext_OpenGL
* @note This is automatically called by RGFW_window_close if the window’s context is not NULL.
+ * @note you should set the window context to NULL with RGFW_window_setContext_OpenGL(win, NULL) after calling this function
+*/
+RGFWDEF void RGFW_deleteContextPtr_OpenGL(RGFW_glContext* ctx);
+
+/**!
+ * @brief allocates a new context, copying the info from an old context
+ * @param ctx A pointer to the RGFW_glContext to copy.
+ * @return The newly allocated context
+*/
+RGFWDEF RGFW_glContext* RGFW_copyContext_OpenGL(RGFW_glContext* ctx);
+
+/**!
+ * @brief copies info from a context to make a new context with the supplied pointer
+ * @param ctx A pointer to the RGFW_glContext to copy.
+ * @param newCtx A pointer to the new context.
+ * @return boolean RGFW_TRUE for success, RGFW_FALSE for failure
+*/
+RGFWDEF RGFW_bool RGFW_copyContextPtr_OpenGL(RGFW_glContext* ctx, RGFW_glContext* newCtx);
+
+/**!
+ * @brief sets the window's context to a context that was already created
+ * @param win A pointer to the RGFW_window.
+ * @param ctx A pointer to the RGFW_glContext to use.
+ * @return boolean RGFW_TRUE for success, RGFW_FALSE for failure
+*/
+RGFWDEF RGFW_bool RGFW_window_setContext_OpenGL(RGFW_window* win, RGFW_glContext* ctx);
+
+/**!
+ * @brief Retrieves the OpenGL context associated with a window.
+ * @param win A pointer to the RGFW_window.
+ * @return A pointer to the associated RGFW_glContext, or NULL if none exists or if the context is EGL-based.
*/
-RGFWDEF void RGFW_window_deleteContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx);
+RGFWDEF RGFW_glContext* RGFW_window_getContext_OpenGL(RGFW_window* win);
/**!
* @brief Retrieves the native source context from an RGFW_glContext.
@@ -2421,6 +2599,12 @@ RGFWDEF void RGFW_window_swapBuffers_OpenGL(RGFW_window* win);
RGFWDEF void* RGFW_getCurrentContext_OpenGL(void);
/**!
+ * @brief Retrieves the current OpenGL surface.
+ * @return A pointer to the currently active OpenGL surface (GLX, WGL, Cocoa, or WebGL backend).
+*/
+RGFWDEF void* RGFW_getCurrentSurface_OpenGL(void);
+
+/**!
* @brief Retrieves the current OpenGL window.
* @return A pointer to the RGFW_window currently bound as the OpenGL context target.
*/
@@ -2455,43 +2639,66 @@ RGFWDEF RGFW_bool RGFW_extensionSupported_OpenGL(const char* extension, size_t l
* @return RGFW_TRUE if supported, RGFW_FALSE otherwise.
*/
RGFWDEF RGFW_bool RGFW_extensionSupportedPlatform_OpenGL(const char* extension, size_t len);
+#endif
-/* these are EGL specific functions, they may fallback to OpenGL */
#ifdef RGFW_EGL
+
+/* these are EGL specific functions, they may fallback to OpenGL */
/**!
- * @brief Creates and allocates an OpenGL/EGL context for the specified window.
- * @param win A pointer to the target RGFW_window.
+ * @brief Creates and allocates an OpenGL/EGL context that can be attached to a window.
* @param hints A pointer to an RGFW_glHints structure defining context creation parameters.
* @return A pointer to the newly created RGFW_eglContext.
*/
-RGFWDEF RGFW_eglContext* RGFW_window_createContext_EGL(RGFW_window* win, RGFW_glHints* hints);
+RGFWDEF RGFW_eglContext* RGFW_createContext_EGL(RGFW_glHints* hints);
/**!
- * @brief Creates an OpenGL/EGL context for the specified window using a preallocated context structure.
- * @param win A pointer to the target RGFW_window.
+ * @brief Creates an OpenGL/EGL context that can be attached to a window, using a preallocated context structure.
* @param ctx A pointer to an already allocated RGFW_eglContext structure.
* @param hints A pointer to an RGFW_glHints structure defining context creation parameters.
* @return RGFW_TRUE on success, RGFW_FALSE on failure.
*/
-RGFWDEF RGFW_bool RGFW_window_createContextPtr_EGL(RGFW_window* win, RGFW_eglContext* ctx, RGFW_glHints* hints);
+RGFWDEF RGFW_bool RGFW_createContextPtr_EGL(RGFW_eglContext* ctx, RGFW_glHints* hints);
/**!
* @brief Frees and deletes an OpenGL/EGL context.
- * @param win A pointer to the RGFW_window.
* @param ctx A pointer to the RGFW_eglContext to delete.
*
* @note Automatically called by RGFW_window_close if RGFW owns the context.
+ * @note you should set the window context to NULL with RGFW_window_setContext_OpenGL(win, NULL) after calling this function
*/
-RGFWDEF void RGFW_window_deleteContext_EGL(RGFW_window* win, RGFW_eglContext* ctx);
+RGFWDEF void RGFW_deleteContext_EGL(RGFW_eglContext* ctx);
/**!
* @brief Deletes an OpenGL/EGL context without freeing its memory.
- * @param win A pointer to the RGFW_window.
* @param ctx A pointer to the RGFW_eglContext to delete.
*
* @note Automatically called by RGFW_window_close if RGFW owns the context.
+ * @note you should set the window context to NULL with RGFW_window_setContext_OpenGL(win, NULL) after calling this function
+*/
+RGFWDEF void RGFW_deleteContextPtr_EGL(RGFW_eglContext* ctx);
+
+/**!
+ * @brief allocates a new context, copying the info from an old context
+ * @param ctx A pointer to the RGFW_eglContext to copy.
+ * @return The newly allocated context
+*/
+RGFWDEF RGFW_eglContext* RGFW_copyContext_EGL(RGFW_eglContext* ctx);
+
+/**!
+ * @brief copies info from a context to make a new context with the supplied pointer
+ * @param ctx A pointer to the RGFW_eglContext to copy.
+ * @param newCtx A pointer to the new context.
+ * @return boolean RGFW_TRUE for success, RGFW_FALSE for failure
*/
-RGFWDEF void RGFW_window_deleteContextPtr_EGL(RGFW_window* win, RGFW_eglContext* ctx);
+RGFWDEF RGFW_bool RGFW_copyContextPtr_EGL(RGFW_eglContext* ctx, RGFW_eglContext* newCtx);
+
+/**!
+ * @brief sets the window's context to a context that was already created
+ * @param win A pointer to the RGFW_window.
+ * @param ctx A pointer to the RGFW_eglContext to use.
+ * @return boolean RGFW_TRUE for success, RGFW_FALSE for failure
+*/
+RGFWDEF RGFW_bool RGFW_window_setContext_EGL(RGFW_window* win, RGFW_eglContext* ctx);
/**!
* @brief Retrieves the OpenGL/EGL context associated with a window.
@@ -2559,6 +2766,12 @@ RGFWDEF void RGFW_window_makeCurrentContext_EGL(RGFW_window* win);
RGFWDEF void* RGFW_getCurrentContext_EGL(void);
/**!
+ * @brief Retrieves the current EGL surface.
+ * @return A pointer to the currently active EGLSurface.
+*/
+RGFWDEF void* RGFW_getCurrentSurface_EGL(void);
+
+/**!
* @brief Retrieves the current EGL window.
* @return A pointer to the RGFW_window currently bound as the EGL context target.
*/
@@ -2593,13 +2806,17 @@ RGFWDEF RGFW_bool RGFW_extensionSupported_EGL(const char* extension, size_t len)
* @return RGFW_TRUE if supported, RGFW_FALSE otherwise.
*/
RGFWDEF RGFW_bool RGFW_extensionSupportedPlatform_EGL(const char* extension, size_t len);
-#endif
-#endif
-#ifdef RGFW_VULKAN
-#include <vulkan/vulkan.h>
+#endif /* RGFW_EGL */
-/* if you don't want to use the above macros */
+#ifdef RGFW_VULKAN
+/**!
+ * @brief Retrieves the address of a Vulkan procedure using a Vulkan instance.
+ * @param the Vulkan Instance to use
+ * @param procname The name of the Vulkan function to look up.
+ * @return A pointer to the function, or NULL if not found.
+*/
+RGFWDEF RGFW_proc RGFW_getInstanceProcAddress_Vulkan(VkInstance instance, const char* procname);
/**!
* @brief Retrieves the Vulkan instance extensions required by RGFW.
@@ -2624,7 +2841,7 @@ RGFWDEF VkResult RGFW_window_createSurface_Vulkan(RGFW_window* win, VkInstance i
* @param queueFamilyIndex The index of the queue family to query for presentation support.
* @return RGFW_TRUE if presentation is supported, RGFW_FALSE otherwise.
*/
-RGFWDEF RGFW_bool RGFW_getPresentationSupport_Vulkan(VkPhysicalDevice physicalDevice, u32 queueFamilyIndex);
+RGFWDEF RGFW_bool RGFW_getPhysicalDevicePresentationSupport_Vulkan(VkInstance instance, VkPhysicalDevice physicalDevice, u32 queueFamilyIndex);
#endif
#ifdef RGFW_DIRECTX
@@ -2645,7 +2862,7 @@ RGFWDEF RGFW_bool RGFW_getPresentationSupport_Vulkan(VkPhysicalDevice physicalDe
* @param swapchain [OUTPUT] A pointer to an IDXGISwapChain pointer that will receive the created swap chain.
* @return An integer result code (0 on success, or a DirectX error code on failure).
*/
-RGFWDEF int RGFW_window_createSwapChain_DirectX(RGFW_window* win, IDXGIFactory* pFactory, IUnknown* pDevice, IDXGISwapChain** swapchain);
+RGFWDEF i32 RGFW_window_createSwapChain_DirectX(RGFW_window* win, IDXGIFactory* pFactory, IUnknown* pDevice, IDXGISwapChain** swapchain);
#endif
#endif
@@ -2728,75 +2945,34 @@ RGFWDEF u32 RGFW_rgfwToApiKey(RGFW_key keycode);
*/
RGFWDEF RGFW_key RGFW_physicalToMappedKey(RGFW_key keycode);
-/**!
- * @brief Retrieves the size of the RGFW_info structure.
- * @return The size (in bytes) of RGFW_info.
-*/
-RGFWDEF size_t RGFW_sizeofInfo(void);
-
-/**!
- * @brief Initializes the RGFW library.
- * @return 0 on success, or a negative error code on failure.
- * @note This is automatically called when the first window is created.
-*/
-RGFWDEF i32 RGFW_init(void);
-
-/**!
- * @brief Deinitializes the RGFW library.
- * @note This is automatically called when the last open window is closed.
-*/
-RGFWDEF void RGFW_deinit(void);
-
-/**!
- * @brief Initializes RGFW using a user-provided RGFW_info structure.
- * @param info A pointer to an RGFW_info structure to be used for initialization.
- * @return 0 on success, or a negative error code on failure.
-*/
-RGFWDEF i32 RGFW_init_ptr(RGFW_info* info);
-
-/**!
- * @brief Deinitializes a specific RGFW instance stored in the provided RGFW_info pointer.
- * @param info A pointer to the RGFW_info structure representing the instance to deinitialize.
-*/
-RGFWDEF void RGFW_deinit_ptr(RGFW_info* info);
-
-/**!
- * @brief Sets the global RGFW_info structure pointer.
- * @param info A pointer to the RGFW_info structure to set.
-*/
-RGFWDEF void RGFW_setInfo(RGFW_info* info);
-
-/**!
- * @brief Retrieves the global RGFW_info structure pointer.
- * @return A pointer to the current RGFW_info structure.
-*/
-RGFWDEF RGFW_info* RGFW_getInfo(void);
-
/** @} */
#endif /* RGFW_HEADER */
#if !defined(RGFW_NATIVE_HEADER) && (defined(RGFW_NATIVE) || defined(RGFW_IMPLEMENTATION))
#define RGFW_NATIVE_HEADER
- #if (defined(RGFW_OPENGL) || defined(RGFW_WEGL)) && defined(_MSC_VER)
- #pragma comment(lib, "opengl32")
- #endif
-
- #ifdef RGFW_OPENGL
+ #ifdef RGFW_EGL
struct RGFW_eglContext {
void* ctx;
void* surface;
+ void* config;
struct wl_egl_window* eglWindow;
};
+ #endif
+ #if defined(RGFW_OPENGL) || defined(RGFW_EGL)
typedef union RGFW_gfxContext {
- RGFW_glContext* native;
- RGFW_eglContext* egl;
+ #ifdef RGFW_OPENGL
+ RGFW_glContext* native;
+ #endif
+
+ #ifdef RGFW_EGL
+ RGFW_eglContext* egl;
+ #endif
} RGFW_gfxContext;
typedef RGFW_ENUM(u32, RGFW_gfxContextType) {
RGFW_gfxNativeOpenGL = RGFW_BIT(0),
- RGFW_gfxEGL = RGFW_BIT(1),
- RGFW_gfxOwnedByRGFW = RGFW_BIT(2)
+ RGFW_gfxEGL = RGFW_BIT(1)
};
#endif
@@ -2820,7 +2996,7 @@ RGFWDEF RGFW_info* RGFW_getInfo(void);
};
#ifdef RGFW_OPENGL
- struct RGFW_glContext { HGLRC ctx; };
+ struct RGFW_glContext { HGLRC ctx; i32 format; };
#endif
struct RGFW_window_src {
@@ -2830,7 +3006,7 @@ RGFWDEF RGFW_info* RGFW_getInfo(void);
i32 maxSizeW, maxSizeH, minSizeW, minSizeH, aspectRatioW, aspectRatioH; /*!< for setting max/min resize (RGFW_WINDOWS) */
RGFW_bool actionFrame; /* frame after a caption button was toggled (e.g. minimize, maximize or close) */
WCHAR highSurrogate;
- #ifdef RGFW_OPENGL
+ #if defined(RGFW_OPENGL) || defined(RGFW_EGL)
RGFW_gfxContext ctx;
RGFW_gfxContextType gfxType;
#endif
@@ -2841,10 +3017,8 @@ RGFWDEF RGFW_info* RGFW_getInfo(void);
#include <X11/Xlib.h>
#include <X11/Xutil.h>
- #ifndef RGFW_NO_XRANDR
- #include <X11/extensions/Xrandr.h>
- #include <X11/Xresource.h>
- #endif
+ #include <X11/extensions/Xrandr.h>
+ #include <X11/Xresource.h>
#ifndef RGFW_XDND_VERSION
#define RGFW_XDND_VERSION 5
@@ -2873,10 +3047,11 @@ RGFWDEF RGFW_info* RGFW_getInfo(void);
RGFW_format format;
};
- #ifdef RGFW_OPENGL
+ #if defined(RGFW_OPENGL) || defined(RGFW_EGL)
struct RGFW_glContext {
#ifdef RGFW_X11
struct __GLXcontextRec* ctx; /*!< source graphics context */
+ void* config;
Window window;
#endif
#ifdef RGFW_WAYLAND
@@ -2887,7 +3062,7 @@ RGFWDEF RGFW_info* RGFW_getInfo(void);
struct RGFW_window_src {
i32 x, y, w, h;
- #ifdef RGFW_OPENGL
+ #if defined(RGFW_OPENGL) || defined(RGFW_EGL)
RGFW_gfxContext ctx;
RGFW_gfxContextType gfxType;
#endif
@@ -2954,7 +3129,7 @@ RGFWDEF RGFW_info* RGFW_getInfo(void);
void* view; /* apple viewpoint thingy */
void* mouse;
void* delegate;
- #ifdef RGFW_OPENGL
+ #if defined(RGFW_OPENGL) || defined(RGFW_EGL)
RGFW_gfxContext ctx;
RGFW_gfxContextType gfxType;
#endif
@@ -2969,14 +3144,14 @@ RGFWDEF RGFW_info* RGFW_getInfo(void);
RGFW_format format;
};
- #ifdef RGFW_OPENGL
+ #if defined(RGFW_OPENGL) || defined(RGFW_EGL)
struct RGFW_glContext {
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx;
};
#endif
struct RGFW_window_src {
- #ifdef RGFW_OPENGL
+ #if defined(RGFW_OPENGL) || defined(RGFW_EGL)
RGFW_gfxContext ctx;
RGFW_gfxContextType gfxType;
#endif
@@ -3007,7 +3182,9 @@ typedef struct RGFW_windowInternal {
RGFW_eventFlag enabledEvents;
u32 flags; /*!< windows flags (for RGFW to check and modify) */
i32 oldX, oldY, oldW, oldH;
- RGFW_monitorMode oldMode;
+ RGFW_bool oldBorderless;
+ RGFW_monitor* monitor;
+ RGFW_monitorMode oldMode, newMode;
RGFW_mouse* mouse;
} RGFW_windowInternal;
@@ -3015,6 +3192,7 @@ struct RGFW_window {
RGFW_window_src src; /*!< src window data */
RGFW_windowInternal internal; /*!< internal window data that is not specific to the OS */
void* userPtr; /* ptr for user data */
+ RGFW_window* next; /* pointer to the next RGFW window in the same context */
i32 x, y, w, h; /*!< position and size of the window */
}; /*!< window structure for the window */
@@ -3022,7 +3200,7 @@ typedef struct RGFW_windowState {
RGFW_bool mouseEnter;
RGFW_bool dataDragging;
RGFW_bool dataDrop;
- size_t dataSize;
+ size_t dataLength;
i32 dropX, dropY;
RGFW_window* win; /*!< it's not possible for one of these events to happen in the frame that the other event happened */
@@ -3046,8 +3224,7 @@ struct RGFW_monitorNode {
RGFW_monitorMode* modes;
size_t modeCount;
#endif
-#if defined(RGFW_X11) && !defined(RGFW_NO_XRANDR)
- i32 screen;
+#if defined(RGFW_X11)
RROutput rrOutput;
RRCrtc crtc;
#endif
@@ -3060,6 +3237,7 @@ struct RGFW_monitorNode {
void* screen;
CGDirectDisplayID display;
u32 uintNum;
+ CFArrayRef allModes;
#endif
};
@@ -3070,18 +3248,17 @@ typedef struct RGFW_monitorList {
typedef struct RGFW_monitors {
RGFW_monitorList list;
- RGFW_monitorList freeList;
size_t count;
RGFW_monitorNode* primary;
- RGFW_monitorNode data[RGFW_MAX_MONITORS];
+ #if (RGFW_PREALLOCATED_MONITORS)
+ RGFW_monitorList freeList;
+ RGFW_monitorNode data[RGFW_PREALLOCATED_MONITORS];
+ #endif
} RGFW_monitors;
-RGFWDEF RGFW_monitorNode* RGFW_monitors_add(const RGFW_monitor* mon);
-RGFWDEF void RGFW_monitors_remove(RGFW_monitorNode* node, RGFW_monitorNode* prev);
-
struct RGFW_info {
- RGFW_window* root;
+ RGFW_window* root, * cur;
i32 windowCount;
RGFW_mouse* hiddenMouse;
@@ -3107,24 +3284,20 @@ struct RGFW_info {
RGFW_key keycodes[256];
#endif
- const char* className;
- RGFW_bool useWaylandBool;
RGFW_bool stopCheckEvents_bool ;
u64 timerOffset;
- char* clipboard_data;
- char* clipboard; /* for writing to the clipboard selection */
- size_t clipboard_len;
+ RGFW_dataTransfer* clipboard;
RGFW_bool dndBuild;
RGFW_dataDropNode* dndRoot;
RGFW_dataDropNode* dndCur;
#ifdef RGFW_X11
+ const char* className;
Display* display;
XContext context;
Window helperWindow;
- const char* instName;
XErrorEvent* x11Error;
i32 xrandrEventBase;
XIM im;
@@ -3132,7 +3305,44 @@ struct RGFW_info {
long x11Version;
i32 x11Format;
RGFW_dataTransferType x11TransferType;
- #endif
+ Atom _NET_WORKAREA,
+ _NET_CURRENT_DESKTOP,
+ _NET_WM_STATE_MAXIMIZED_VERT,
+ _NET_WM_STATE_MAXIMIZED_HORZ,
+ _NET_WM_BYPASS_COMPOSITOR,
+ _NET_WM_STATE,
+ _MOTIF_WM_HINTS,
+ WM_DELETE_WINDOW,
+ _NET_WM_SYNC_REQUEST_COUNTER,
+ _NET_WM_SYNC_REQUEST,
+ ATOM_PAIR,
+ MULTIPLE,
+ TARGETS,
+ SAVE_TARGETS,
+ UTF8_STRING,
+ XdndAware,
+ XdndTypeList,
+ XdndSelection,
+ XdndEnter,
+ XdndPosition,
+ XdndStatus,
+ XdndLeave,
+ XdndDrop,
+ XdndFinished,
+ XdndActionCopy,
+ WM_PROTOCOLS,
+ WM_STATE,
+ _NET_WM_STATE_FULLSCREEN,
+ _NET_WM_STATE_ABOVE,
+ NET_WM_WINDOW_OPACITY,
+ _NET_WM_NAME,
+ _NET_WM_ICON,
+ XSEL_DATA,
+ CLIPBOARD,
+ CLIPBOARD_MANAGER,
+ XtextUriList,
+ XtextPlain;
+ #endif
#ifdef RGFW_WAYLAND
struct wl_display* wl_display;
struct xkb_context *xkb_context;
@@ -3168,13 +3378,20 @@ struct RGFW_info {
u32 last_key; /* wayland key repeat data */
i32 wl_repeat_info_rate, wl_repeat_info_delay;
u32 last_key_time;
- #endif
+ RGFW_bool useWaylandBool;
+ #endif
+ #ifdef RGFW_WINDOWS
+ HINSTANCE instance;
+ WNDCLASSW wndClass;
+ HWND helperWindow;
+ wchar_t wideClassName[256];
+ #endif
RGFW_monitors monitors;
#ifdef RGFW_UNIX
int eventWait_forceStop[3];
- i32 clock;
+ RGFW_dataTransfer* unixClipboard;
#endif
#ifdef RGFW_MACOS
@@ -3183,15 +3400,39 @@ struct RGFW_info {
void* customViewClasses[2]; /* NSView and NSOpenGLView */
void* customNSAppDelegateClass;
void* customWindowDelegateClass;
+ void* customWindowClass;
void* customNSAppDelegate;
void* tisBundle;
#endif
- #ifdef RGFW_OPENGL
+ #if defined(RGFW_OPENGL) || defined(RGFW_EGL)
RGFW_window* current;
#endif
+ #ifdef RGFW_OPENGL
+ void* nativeGL_handle;
+ RGFW_proc (*glGetProcAddress)(const char*);
+ #endif
#ifdef RGFW_EGL
void* EGL_display;
+ void* EGL_handle;
+ RGFW_proc (*eglGetProcAddress)(const char*);
+ #endif
+ #ifdef RGFW_VULKAN
+ void* vulkan_handle;
+ RGFW_proc (*vkGetInstanceProcAddress)(void*, const char*);
+ #if defined(RGFW_X11)
+ RGFW_vkCreateXlibSurfaceKHRProc vkCreateXlibSurfaceKHR;
+ RGFW_vkGetPhysicalDeviceXlibPresentationSupportKHRProc vkGetPhysicalDeviceXlibPresentationSupportKHR;
+ #endif
+ #ifdef RGFW_WAYLAND
+ RGFW_vkCreateWaylandSurfaceKHRProc vkCreateWaylandSurfaceKHR;
+ RGFW_vkGetPhysicalDeviceWaylandPresentationSupportKHRProc vkGetPhysicalDeviceWaylandPresentationSupportKHR;
+ #endif
+
+ #ifdef RGFW_WINDOWS
+ RGFW_vkCreateWin32SurfaceKHRProc vkCreateWin32SurfaceKHR;
+ RGFW_vkGetPhysicalDeviceWin32PresentationSupportKHRProc vkGetPhysicalDeviceWin32PresentationSupportKHR;
+ #endif
#endif
RGFW_bool rawMouse; /* global raw mouse toggle */
@@ -3211,25 +3452,45 @@ struct RGFW_info {
#include <math.h>
#endif
+#if defined(RGFW_MACOS) || defined(RGFW_UNIX)
+ #include <dlfcn.h>
+#endif
+
/* global private API */
/* for C++ / C89 */
RGFWDEF RGFW_window* RGFW_createWindowPlatform(const char* name, RGFW_windowFlags flags, RGFW_window* win);
RGFWDEF void RGFW_window_closePlatform(RGFW_window* win);
RGFWDEF RGFW_bool RGFW_window_setMousePlatform(RGFW_window* win, RGFW_mouse* mouse);
-
+RGFWDEF void RGFW_window_showPlatform(RGFW_window* win);
+RGFWDEF void RGFW_window_restorePlatform(RGFW_window* win);
+RGFWDEF void RGFW_window_minimizePlatform(RGFW_window* win);
+RGFWDEF void RGFW_window_movePlatform(RGFW_window* win, i32 x, i32 y);
+RGFWDEF void RGFW_window_resizePlatform(RGFW_window* win, i32 w, i32 h);
+RGFWDEF void RGFW_window_maximizePlatform(RGFW_window* win);
+RGFWDEF void RGFW_window_setFullscreenPlatform(RGFW_window* win, RGFW_bool fullscreen);
RGFWDEF void RGFW_window_setFlagsInternal(RGFW_window* win, RGFW_windowFlags flags, RGFW_windowFlags cmpFlags);
RGFWDEF void RGFW_initKeycodes(void);
RGFWDEF void RGFW_initKeycodesPlatform(void);
RGFWDEF void RGFW_resetPrevState(void);
RGFWDEF void RGFW_resetKey(void);
-RGFWDEF void RGFW_unloadEGL(void);
RGFWDEF void RGFW_keyUpdateKeyModsEx(RGFW_window* win, RGFW_bool capital, RGFW_bool numlock, RGFW_bool control, RGFW_bool alt, RGFW_bool shift, RGFW_bool super, RGFW_bool scroll);
RGFWDEF void RGFW_keyUpdateKeyMods(RGFW_window* win, RGFW_bool capital, RGFW_bool numlock, RGFW_bool scroll);
RGFWDEF void RGFW_window_showMouseFlags(RGFW_window* win, RGFW_bool show);
RGFWDEF void RGFW_keyUpdateKeyMod(RGFW_window* win, RGFW_keymod mod, RGFW_bool value);
+
+RGFWDEF RGFW_bool RGFW_loadGL(void);
+RGFWDEF void RGFW_unloadGL(void);
+RGFWDEF RGFW_bool RGFW_loadEGL(void);
+RGFWDEF void RGFW_unloadEGL(void);
+RGFWDEF RGFW_bool RGFW_loadVulkan(void);
+RGFWDEF void RGFW_unloadVulkan(void);
+
RGFWDEF void RGFW_monitors_refresh(void);
+RGFWDEF RGFW_monitorNode* RGFW_monitors_add(const RGFW_monitor* mon);
+RGFWDEF void RGFW_monitors_remove(RGFW_monitorNode* node, RGFW_monitorNode* prev);
+RGFWDEF void RGFW_monitorNode_free(RGFW_monitorNode* node);
RGFWDEF void RGFW_windowMaximizedCallback(RGFW_window* win, i32 x, i32 y, i32 w, i32 h);
RGFWDEF void RGFW_windowMinimizedCallback(RGFW_window* win);
@@ -3237,7 +3498,7 @@ RGFWDEF void RGFW_windowRestoredCallback(RGFW_window* win, i32 x, i32 y, i32 w,
RGFWDEF void RGFW_windowMovedCallback(RGFW_window* win, i32 x, i32 y);
RGFWDEF void RGFW_windowResizedCallback(RGFW_window* win, i32 w, i32 h);
RGFWDEF void RGFW_windowCloseCallback(RGFW_window* win);
-RGFWDEF void RGFW_mousePosCallback(RGFW_window* win, i32 x, i32 y);
+RGFWDEF void RGFW_mouseMotionCallback(RGFW_window* win, i32 x, i32 y);
RGFWDEF void RGFW_rawMotionCallback(RGFW_window* win, float x, float y);
RGFWDEF void RGFW_windowRefreshCallback(RGFW_window* win, i32 x, i32 y, i32 w, i32 h);
RGFWDEF void RGFW_windowFocusCallback(RGFW_window* win, RGFW_bool inFocus);
@@ -3260,9 +3521,7 @@ RGFWDEF void RGFW_window_setRawMouseModePlatform(RGFW_window *win, RGFW_bool sta
RGFWDEF void RGFW_copyImageData64(u8* dest_data, i32 w, i32 h, RGFW_format dest_format,
u8* src_data, RGFW_format src_format, RGFW_bool is64bit, RGFW_convertImageDataFunc func);
-RGFWDEF RGFW_bool RGFW_loadEGL(void);
-
-#ifdef RGFW_OPENGL
+#if defined(RGFW_OPENGL) || defined(RGFW_EGL)
typedef struct RGFW_attribStack {
i32* attribs;
size_t count;
@@ -3275,11 +3534,31 @@ RGFWDEF void RGFW_attribStack_pushAttribs(RGFW_attribStack* stack, i32 attrib1,
RGFWDEF RGFW_bool RGFW_extensionSupportedStr(const char* extensions, const char* ext, size_t len);
#endif
+#ifndef RGFW_EGL
+RGFW_bool RGFW_loadEGL(void) { return RGFW_FALSE; }
+void RGFW_unloadEGL(void) { }
+#endif
+
+#ifndef RGFW_OPENGL
+RGFW_bool RGFW_loadGL(void) { return RGFW_FALSE; }
+void RGFW_unloadGL(void) { }
+#endif
+
+#ifndef RGFW_VULKAN
+RGFW_bool RGFW_loadVulkan(void) { return RGFW_FALSE; }
+void RGFW_unloadVulkan(void) { }
+#endif
+
#ifdef RGFW_X11
-RGFWDEF void RGFW_XCreateWindow (XVisualInfo visual, const char* name, RGFW_windowFlags flags, RGFW_window* win);
+RGFWDEF RGFW_bool RGFW_XCreateWindow (XVisualInfo visual, const char* name, RGFW_windowFlags flags, RGFW_window* win);
+RGFWDEF char* RGFW_XGetWindowName(Window window);
#endif
#ifdef RGFW_MACOS
RGFWDEF void RGFW_osx_initView(RGFW_window* win);
+
+ #ifdef RGFW_OPENGL
+ RGFWDEF void RGFW_copyContext_OSX_OpenGL(RGFW_glContext* ctx, RGFW_glContext* newCtx);
+ #endif
#endif
/* end of global private API defs */
@@ -3291,46 +3570,38 @@ RGFW_info* RGFW_getInfo(void) { return _RGFW; }
void* RGFW_alloc(size_t size) { return RGFW_ALLOC(size); }
void RGFW_free(void* ptr) { RGFW_FREE(ptr); }
-void RGFW_useWayland(RGFW_bool wayland) { RGFW_init(); _RGFW->useWaylandBool = RGFW_BOOL(wayland); }
-RGFW_bool RGFW_usingWayland(void) { return _RGFW->useWaylandBool; }
-
void RGFW_setRawMouseMode(RGFW_bool state) {
_RGFW->rawMouse = state;
RGFW_window_setRawMouseModePlatform(_RGFW->root, state);
}
-void RGFW_clipboard_switch(char* newstr);
-void RGFW_clipboard_switch(char* newstr) {
- if (_RGFW->clipboard_data != NULL)
- RGFW_FREE(_RGFW->clipboard_data);
- _RGFW->clipboard_data = newstr;
-}
-
-#define RGFW_CHECK_CLIPBOARD() \
- if (size <= 0 && _RGFW->clipboard_data != NULL) \
- return (const char*)_RGFW->clipboard_data; \
- else if (size <= 0) \
- return "\0";
+const RGFW_dataTransfer* RGFW_readClipboard(RGFW_dataTransferType requestedType) {
+ RGFW_dataTransfer data_check;
+ RGFW_bool ret = RGFW_readClipboardPtr(requestedType, NULL, 0, &data_check);
+ if (ret == RGFW_FALSE || data_check.length == 0) return _RGFW->clipboard;
-const char* RGFW_readClipboard(size_t* len) {
- RGFW_ssize_t size = RGFW_readClipboardPtr(NULL, 0);
- RGFW_CHECK_CLIPBOARD();
- char* str = (char*)RGFW_ALLOC((size_t)size);
- RGFW_ASSERT(str != NULL);
- str[0] = '\0';
+ u8* cont_data = (u8*)RGFW_ALLOC(sizeof(RGFW_dataTransfer) + (size_t)data_check.length);
+ RGFW_ASSERT(cont_data != NULL);
- size = RGFW_readClipboardPtr(str, (size_t)size);
+ RGFW_dataTransfer* data = (RGFW_dataTransfer*)(void*)cont_data;
+ ret = RGFW_readClipboardPtr(requestedType, (u8*)&cont_data[sizeof(RGFW_dataTransfer) - 1], data_check.length, data);
- RGFW_CHECK_CLIPBOARD();
+ if (ret == RGFW_FALSE || data->length == 0) {
+ RGFW_FREE(cont_data);
+ data = NULL;
+ } else if (_RGFW->clipboard) {
+ RGFW_FREE(_RGFW->clipboard);
+ }
- if (len != NULL) *len = (size_t)size;
+ _RGFW->clipboard = data;
- RGFW_clipboard_switch(str);
- return (const char*)str;
+ return _RGFW->clipboard;
}
-/* generic RGFW defines */
+const RGFW_dataTransfer* RGFW_readClipboardString(void) { return RGFW_readClipboard(RGFW_dataText); }
+RGFW_bool RGFW_readClipboardStringPtr(u8* buffer, size_t capacity, RGFW_dataTransfer* data) { return RGFW_readClipboardPtr(RGFW_dataText, buffer, capacity, data); }
+/* generic RGFW defines */
void RGFW_initKeycodes(void) {
RGFW_MEMZERO(_RGFW->keycodes, sizeof(_RGFW->keycodes));
RGFW_initKeycodesPlatform();
@@ -3368,7 +3639,7 @@ void RGFW_resetKey(void) { RGFW_MEMZERO(_RGFW->keyboard, sizeof(_RGFW->keyboard)
RGFW_genericFunc RGFW_setEventCallback(RGFW_eventType type, RGFW_genericFunc func) {
RGFW_ASSERT(type > RGFW_eventNone && type < RGFW_eventCount);
- RGFW_init();
+ RGFW_ASSERT(_RGFW && "An RGFW context must be initialized using RGFW_init and/or set with RGFW_setInfo");
RGFW_genericFunc old = _RGFW->callbacks[type];
_RGFW->callbacks[type] = func;
@@ -3392,7 +3663,8 @@ void RGFW_setAllEventCallbacks(RGFW_genericFunc func, RGFW_callbacks* callbacks)
}
RGFW_debugFunc RGFW_setDebugCallback(RGFW_debugFunc func) {
- RGFW_init();
+ RGFW_ASSERT(_RGFW && "An RGFW context must be initialized using RGFW_init and/or set with RGFW_setInfo");
+
RGFW_debugFunc prev = _RGFW->debugCallbackSrc;
_RGFW->debugCallbackSrc = func;
return prev;
@@ -3467,7 +3739,7 @@ void RGFW_windowMovedCallback(RGFW_window* win, i32 x, i32 y) {
RGFW_event event;
event.type = RGFW_windowMoved;
event.update.x = x;
- event.update.x = y;
+ event.update.y = y;
event.update.w = win->w;
event.update.h = win->h;
event.common.win = win;
@@ -3498,14 +3770,14 @@ void RGFW_windowCloseCallback(RGFW_window* win) {
RGFW_eventQueuePushAndCall(&event);
}
-void RGFW_mousePosCallback(RGFW_window* win, i32 x, i32 y) {
+void RGFW_mouseMotionCallback(RGFW_window* win, i32 x, i32 y) {
win->internal.lastMouseX = x;
win->internal.lastMouseY = y;
- if (!(win->internal.enabledEvents & RGFW_mousePosChangedFlag)) return;
+ if (!(win->internal.enabledEvents & RGFW_mouseMotionFlag)) return;
RGFW_event event;
- event.type = RGFW_mousePosChanged;
+ event.type = RGFW_mouseMotion;
event.mouse.x = x;
event.mouse.y = y;
event.mouse.inWindow = win->internal.mouseInside;
@@ -3549,14 +3821,24 @@ void RGFW_windowFocusCallback(RGFW_window* win, RGFW_bool inFocus) {
event.common.win = win;
event.focus.state = inFocus;
+ #ifdef RGFW_MACOS
+ if (RGFW_window_isFullscreen(win)) {
+ RGFW_window_setFullscreenPlatform(win, inFocus);
+ }
+ #endif
+
if (inFocus == RGFW_TRUE) {
- if ((win->internal.flags & RGFW_windowFullscreen))
+ if ((win->internal.flags & RGFW_windowFullscreenExclusive) && win->internal.monitor) {
RGFW_window_raise(win);
+ RGFW_monitor_setMode(win->internal.monitor, &win->internal.newMode);
+ }
event.type = RGFW_windowFocusIn;
} else if (inFocus == RGFW_FALSE) {
- if ((win->internal.flags & RGFW_windowFullscreen))
+ if ((win->internal.flags & RGFW_windowFullscreenExclusive) && win->internal.monitor) {
RGFW_window_minimize(win);
+ RGFW_monitor_setMode(win->internal.monitor, &win->internal.oldMode);
+ }
size_t key;
for (key = 0; key < RGFW_keyLast; key++) {
@@ -3605,18 +3887,18 @@ void RGFW_mouseNotifyCallback(RGFW_window* win, i32 x, i32 y, RGFW_bool status)
RGFW_eventQueuePushAndCall(&event);
}
-void RGFW_dataDropCallback(RGFW_window* win, const char* data, size_t size, RGFW_dataTransferType dataType) {
+void RGFW_dataDropCallback(RGFW_window* win, const char* data, size_t length, RGFW_dataTransferType dataType) {
if (!(win->internal.enabledEvents & RGFW_dataDropFlag) || !(win->internal.flags & RGFW_windowAllowDND))
return;
_RGFW->windowState.win = win;
_RGFW->windowState.dataDrop = RGFW_TRUE;
- _RGFW->windowState.dataSize = size;
+ _RGFW->windowState.dataLength = length;
RGFW_dataDropNode node;
RGFW_MEMZERO(&node, sizeof(node));
node.data = data;
- node.size = size;
+ node.length = length;
node.type = dataType;
node.next = NULL;
@@ -3636,8 +3918,8 @@ void RGFW_dataDropCallback(RGFW_window* win, const char* data, size_t size, RGFW
_RGFW->dndCur = _RGFW->dndCur->next;
} else { RGFW_ASSERT(0); }
- char* dataCopy = (char*)RGFW_ALLOC(size);
- RGFW_MEMCPY(dataCopy, data, size);
+ char* dataCopy = (char*)RGFW_ALLOC(length);
+ RGFW_MEMCPY(dataCopy, data, length);
node.data = dataCopy;
RGFW_MEMCPY(_RGFW->dndCur, &node, sizeof(node));
@@ -3676,10 +3958,10 @@ void RGFW_keyCharCallback(RGFW_window* win, u32 codepoint) {
RGFW_eventQueuePushAndCall(&event);
}
-void RGFW_keyCallback(RGFW_window* win, RGFW_key key, RGFW_keymod mod, RGFW_bool repeat, RGFW_bool press) {
+void RGFW_keyCallback(RGFW_window* win, RGFW_key key, RGFW_keymod mod, RGFW_bool repeat, RGFW_bool state) {
RGFW_event event;
- if (press) {
+ if (state) {
if (!(win->internal.enabledEvents & RGFW_keyPressedFlag)) return;
event.type = RGFW_keyPressed;
} else {
@@ -3688,12 +3970,12 @@ void RGFW_keyCallback(RGFW_window* win, RGFW_key key, RGFW_keymod mod, RGFW_bool
}
_RGFW->keyboard[key].prev = _RGFW->keyboard[key].current;
- _RGFW->keyboard[key].current = press;
+ _RGFW->keyboard[key].current = state;
event.key.value = key;
event.key.repeat = repeat;
event.key.mod = mod;
- event.key.state = press;
+ event.key.state = state;
event.common.win = win;
RGFW_eventQueuePushAndCall(&event);
}
@@ -3802,18 +4084,18 @@ size_t RGFW_sizeofSurface(void) { return sizeof(RGFW_surface); }
size_t RGFW_sizeofWindow(void) { return sizeof(RGFW_window); }
size_t RGFW_sizeofWindowSrc(void) { return sizeof(RGFW_window_src); }
-RGFW_window_src* RGFW_window_getSrc(RGFW_window* win) { return &win->src; }
-RGFW_bool RGFW_window_getPosition(RGFW_window* win, i32* x, i32* y) { if (x) *x = win->x; if (y) *y = win->y; return RGFW_TRUE; }
-RGFW_bool RGFW_window_getSize(RGFW_window* win, i32* w, i32* h) { if (w) *w = win->w; if (h) *h = win->h; return RGFW_TRUE; }
-u32 RGFW_window_getFlags(RGFW_window* win) { return win->internal.flags; }
-RGFW_key RGFW_window_getExitKey(RGFW_window* win) { return win->internal.exitKey; }
-void RGFW_window_setExitKey(RGFW_window* win, RGFW_key key) { win->internal.exitKey = key; }
-void RGFW_window_setEnabledEvents(RGFW_window* win, RGFW_eventFlag events) { win->internal.enabledEvents = events; }
-RGFW_eventFlag RGFW_window_getEnabledEvents(RGFW_window* win) { return win->internal.enabledEvents; }
-void RGFW_window_setDisabledEvents(RGFW_window* win, RGFW_eventFlag events) { RGFW_window_setEnabledEvents(win, (RGFW_allEventFlags) & ~(u32)events); }
-void RGFW_window_setEventState(RGFW_window* win, RGFW_eventFlag event, RGFW_bool state) { RGFW_setBit(&win->internal.enabledEvents, event, state); }
-void* RGFW_window_getUserPtr(RGFW_window* win) { return win->userPtr; }
-void RGFW_window_setUserPtr(RGFW_window* win, void* ptr) { win->userPtr = ptr; }
+RGFW_window_src* RGFW_window_getSrc(RGFW_window* win) { RGFW_ASSERT(win); return &win->src; }
+RGFW_bool RGFW_window_getPosition(RGFW_window* win, i32* x, i32* y) { RGFW_ASSERT(win); if (x) *x = win->x; if (y) *y = win->y; return RGFW_TRUE; }
+RGFW_bool RGFW_window_getSize(RGFW_window* win, i32* w, i32* h) { RGFW_ASSERT(win); if (w) *w = win->w; if (h) *h = win->h; return RGFW_TRUE; }
+u32 RGFW_window_getFlags(RGFW_window* win) { RGFW_ASSERT(win); return win->internal.flags; }
+RGFW_key RGFW_window_getExitKey(RGFW_window* win) { RGFW_ASSERT(win); return win->internal.exitKey; }
+void RGFW_window_setExitKey(RGFW_window* win, RGFW_key key) { RGFW_ASSERT(win); win->internal.exitKey = key; }
+void RGFW_window_setEnabledEvents(RGFW_window* win, RGFW_eventFlag events) { RGFW_ASSERT(win); win->internal.enabledEvents = events; }
+RGFW_eventFlag RGFW_window_getEnabledEvents(RGFW_window* win) { RGFW_ASSERT(win); return win->internal.enabledEvents; }
+void RGFW_window_setDisabledEvents(RGFW_window* win, RGFW_eventFlag events) { RGFW_ASSERT(win); RGFW_window_setEnabledEvents(win, (RGFW_allEventFlags) & ~(u32)events); }
+void RGFW_window_setEventState(RGFW_window* win, RGFW_eventFlag event, RGFW_bool state) { RGFW_ASSERT(win); RGFW_setBit(&win->internal.enabledEvents, event, state); }
+void* RGFW_window_getUserPtr(RGFW_window* win) { RGFW_ASSERT(win); return win->userPtr; }
+void RGFW_window_setUserPtr(RGFW_window* win, void* ptr) { RGFW_ASSERT(win); win->userPtr = ptr; }
RGFW_bool RGFW_window_getSizeInPixels(RGFW_window* win, i32* w, i32* h) {
RGFW_monitor* mon = RGFW_window_getMonitor(win);
@@ -3831,40 +4113,70 @@ RGFW_bool RGFW_window_getSizeInPixels(RGFW_window* win, i32* w, i32* h) {
#include "XDL.h"
#endif
-#ifndef RGFW_FORCE_INIT
-RGFW_info _rgfwGlobal;
-#endif
+#ifndef RGFW_NO_STATIC_CONTEXT
+
+i32 RGFW_init(const char* className, RGFW_initFlags flags) {
+ static RGFW_info _rgfwGlobal;
+ return RGFW_init_ptr(className, flags, &_rgfwGlobal);
+}
+
+
+void RGFW_deinit(void) { RGFW_deinit_ptr(_RGFW); }
+
+#else
-i32 RGFW_init(void) { return RGFW_init_ptr(&_rgfwGlobal); }
-void RGFW_deinit(void) { RGFW_deinit_ptr(&_rgfwGlobal); }
+RGFW_info* _rgfwGlobal;
+
+i32 RGFW_init(const char* className, RGFW_initFlags flags) {
+ if (_rgfwGlobal != NULL) {
+ RGFW_FREE(_rgfwGlobal);
+ }
+
+ _rgfwGlobal = (RGFW_info*)RGFW_ALLOC(sizeof(RGFW_info));
+ return RGFW_init_ptr(className, flags, &_rgfwGlobal);
+}
+
+void RGFW_deinit(void) {
+ if (_RGFW == _rgfwGlobal) {
+ RGFW_FREE(_rgfwGlobal);
+ _rgfwGlobal = NULL;
+ }
+ RGFW_deinit_ptr(_RGFW);
+}
-i32 RGFW_initPlatform(void);
+#endif
+
+i32 RGFW_initPlatform(const char* className, RGFW_initFlags flags);
void RGFW_deinitPlatform(void);
-i32 RGFW_init_ptr(RGFW_info* info) {
+i32 RGFW_init_ptr(const char* className, RGFW_initFlags flags, RGFW_info* info) {
if (info == _RGFW || info == NULL) return 1;
+ className = className ? className : "RGFW";
+
RGFW_setInfo(info);
RGFW_MEMZERO(_RGFW, sizeof(RGFW_info));
- _RGFW->queueEvents = RGFW_FALSE;
- _RGFW->polledEvents = RGFW_FALSE;
-#ifdef RGFW_WAYLAND
- _RGFW->useWaylandBool = RGFW_TRUE;
-#endif
- _RGFW->monitors.freeList.head = &_RGFW->monitors.data[0];
- _RGFW->monitors.freeList.cur = _RGFW->monitors.freeList.head;
+ #if (RGFW_PREALLOCATED_MONITORS)
+ _RGFW->monitors.freeList.head = &_RGFW->monitors.data[0];
+ _RGFW->monitors.freeList.cur = _RGFW->monitors.freeList.head;
- for (size_t i = 1; i < RGFW_MAX_MONITORS; i++) {
- RGFW_monitorNode* newNode = &_RGFW->monitors.data[i];
- _RGFW->monitors.freeList.cur->next = newNode;
- _RGFW->monitors.freeList.cur = _RGFW->monitors.freeList.cur->next;
- }
+ for (size_t i = 1; i < RGFW_PREALLOCATED_MONITORS; i++) {
+ RGFW_monitorNode* newNode = &_RGFW->monitors.data[i];
+ _RGFW->monitors.freeList.cur->next = newNode;
+ _RGFW->monitors.freeList.cur = _RGFW->monitors.freeList.cur->next;
+ }
+ #endif
- _RGFW->monitors.list.head = NULL;
- _RGFW->monitors.list.head = NULL;
RGFW_initKeycodes();
- i32 out = RGFW_initPlatform();
+ i32 out = RGFW_initPlatform(className, flags);
+ if (out != 0) {
+ RGFW_debugCallback(RGFW_typeError, RGFW_infoGlobal, "failed to initialize global context");
+ RGFW_deinitPlatform();
+ RGFW_MEMZERO(_RGFW, sizeof(RGFW_info));
+ RGFW_setInfo(NULL);
+ return out;
+ }
for (size_t i = 0; i < RGFW_mouseIconCount; i++) {
_RGFW->standardMice[i] = RGFW_createMouseStandard((RGFW_mouseIcon)i);
@@ -3872,29 +4184,57 @@ i32 RGFW_init_ptr(RGFW_info* info) {
RGFW_pollMonitors();
+ if (flags & RGFW_initOpenGL) {
+ #ifdef RGFW_WAYLAND
+ if (!(flags & RGFW_initX11)) {
+ flags |= RGFW_initEGL;
+ } else
+ #endif
+
+ if (RGFW_loadGL() == RGFW_FALSE) {
+ RGFW_debugCallback(RGFW_typeError, RGFW_errFailedFuncLoad, "Failed to load the OpenGL library");
+ return -1;
+ }
+ }
+
+ if (flags & RGFW_initVulkan) {
+ if (RGFW_loadVulkan() == RGFW_FALSE) {
+ RGFW_debugCallback(RGFW_typeError, RGFW_errFailedFuncLoad, "Failed to load the Vulkan library");
+ return -1;
+ }
+ }
+
+ if (flags & RGFW_initEGL) {
+ if (RGFW_loadEGL() == RGFW_FALSE) {
+ RGFW_debugCallback(RGFW_typeError, RGFW_errFailedFuncLoad, "Failed to load the EGL library");
+ return -1;
+ }
+ }
+
RGFW_debugCallback(RGFW_typeInfo, RGFW_infoGlobal, "global context initialized");
return out;
}
-#ifndef RGFW_EGL
-void RGFW_unloadEGL(void) { }
-#endif
-
void RGFW_deinit_ptr(RGFW_info* info) {
if (info == NULL) return;
RGFW_setInfo(info);
- RGFW_unloadEGL();
for (RGFW_mouseIcon i = 0; i < RGFW_mouseIconCount; i++) {
if (_RGFW->standardMice[i]) RGFW_freeMouse(_RGFW->standardMice[i]);
}
+ RGFW_freeMonitors();
+
RGFW_debugCallback(RGFW_typeInfo, RGFW_infoGlobal, "global context deinitialized");
RGFW_deinitPlatform();
+ RGFW_unloadEGL();
+ RGFW_unloadGL();
+
_RGFW->root = NULL;
+ _RGFW->cur = NULL;
_RGFW->windowCount = 0;
RGFW_setInfo(NULL);
}
@@ -3912,17 +4252,32 @@ void RGFW_window_close(RGFW_window* win) {
}
RGFW_window* RGFW_createWindowPtr(const char* name, i32 x, i32 y, i32 w, i32 h, RGFW_windowFlags flags, RGFW_window* win) {
+ RGFW_ASSERT(_RGFW && "An RGFW context must be initialized using RGFW_init and/or set with RGFW_setInfo");
RGFW_ASSERT(win != NULL);
if (name == NULL) name = "\0";
- RGFW_MEMZERO(win, sizeof(RGFW_window));
+#ifndef RGFW_OPENGL
+ if ((flags & RGFW_windowOpenGL)) {
+ RGFW_debugCallback(RGFW_typeWarning, RGFW_warningOpenGL, "cannot create an OpenGL context if RGFW is not compiled with OpenGL support via RGFW_OPENGL");
+ flags &= (RGFW_windowFlags)~RGFW_windowOpenGL;
+ }
+#endif
+#ifndef RGFW_EGL
+ if ((flags & RGFW_windowEGL)) {
+ RGFW_debugCallback(RGFW_typeWarning, RGFW_warningOpenGL, "cannot create an EGL context if RGFW is not compiled with EGL support via RGFW_EGL");
+ flags &= (RGFW_windowFlags)~RGFW_windowEGL;
+ }
+#endif
- if (_RGFW == NULL) RGFW_init();
+ RGFW_MEMZERO(win, sizeof(RGFW_window));
_RGFW->windowCount++;
/* rect based the requested flags */
if (_RGFW->root == NULL) {
RGFW_setRootWindow(win);
+ _RGFW->cur = _RGFW->root;
+ } else {
+ _RGFW->cur->next = win;
}
/* set and init the new window's data */
@@ -3933,11 +4288,15 @@ RGFW_window* RGFW_createWindowPtr(const char* name, i32 x, i32 y, i32 w, i32 h,
win->internal.mouse = _RGFW->standardMice[RGFW_mouseNormal];
win->internal.flags = flags;
win->internal.enabledEvents = RGFW_allEventFlags;
+ win->next = NULL;
RGFW_windowFlags reservedFlags = flags & (RGFW_windowScaleToMonitor);
- flags &= ~reservedFlags;
RGFW_window* ret = RGFW_createWindowPlatform(name, flags, win);
+ if (ret == NULL) {
+ RGFW_debugCallback(RGFW_typeError, RGFW_errPlatform, "failed to create a window");
+ return NULL;
+ }
flags |= reservedFlags;
@@ -3947,13 +4306,18 @@ RGFW_window* RGFW_createWindowPtr(const char* name, i32 x, i32 y, i32 w, i32 h,
#ifdef RGFW_OPENGL
win->src.gfxType = 0;
- if (flags & RGFW_windowOpenGL)
- RGFW_window_createContext_OpenGL(win, RGFW_getGlobalHints_OpenGL());
+ if (flags & RGFW_windowOpenGL) {
+ RGFW_glContext* context = RGFW_createContext_OpenGL(RGFW_getGlobalHints_OpenGL());
+ if (context) RGFW_window_setContext_OpenGL(win, context);
+ }
#endif
#ifdef RGFW_EGL
- if (flags & RGFW_windowEGL)
- RGFW_window_createContext_EGL(win, RGFW_getGlobalHints_OpenGL());
+ if (!(flags & RGFW_windowOpenGL)) win->src.gfxType = 0;
+ if (flags & RGFW_windowEGL) {
+ RGFW_eglContext* context = RGFW_createContext_EGL(RGFW_getGlobalHints_OpenGL());
+ if (context) RGFW_window_setContext_EGL(win, context);
+ }
#endif
/* X11 creates the window after the OpenGL context is created (because of visual garbage),
@@ -3965,11 +4329,6 @@ RGFW_window* RGFW_createWindowPtr(const char* name, i32 x, i32 y, i32 w, i32 h,
RGFW_window_setFlagsInternal(win, flags, 0);
#endif
-#ifdef RGFW_MACOS
- /*NOTE: another OpenGL/setFlags related hack, this because OSX the 'view' class must be setup after the NSOpenGL view is made AND after setFlags happens */
- RGFW_osx_initView(win);
-#endif
-
#ifdef RGFW_WAYLAND
/* recieve all events needed to configure the surface */
/* also gets the wl_outputs */
@@ -3987,6 +4346,10 @@ RGFW_window* RGFW_createWindowPtr(const char* name, i32 x, i32 y, i32 w, i32 h,
}
#endif
+#ifdef RGFW_MACOS
+ RGFW_osx_initView(win);
+#endif
+
if (!(flags & RGFW_windowHideMouse)) {
RGFW_window_setMouseDefault(win);
}
@@ -3995,6 +4358,8 @@ RGFW_window* RGFW_createWindowPtr(const char* name, i32 x, i32 y, i32 w, i32 h,
if (!(flags & RGFW_windowHide)) {
flags |= RGFW_windowHide;
RGFW_window_show(win);
+ } else if ((flags & RGFW_windowMaximize) || (flags & RGFW_windowFullscreenExclusive) || (flags & RGFW_windowFullscreenBorderless)) {
+ RGFW_window_hide(win);
}
RGFW_debugCallback(RGFW_typeInfo, RGFW_infoWindow, "a new window was created");
@@ -4004,6 +4369,9 @@ RGFW_window* RGFW_createWindowPtr(const char* name, i32 x, i32 y, i32 w, i32 h,
void RGFW_window_closePtr(RGFW_window* win) {
RGFW_ASSERT(win != NULL);
+ if ((win->internal.flags & RGFW_windowFullscreenExclusive) && win->internal.monitor) {
+ RGFW_monitor_setMode(win->internal.monitor, &win->internal.oldMode);
+ }
if (win->internal.captureMouse) {
RGFW_window_captureMouse(win, RGFW_FALSE);
@@ -4011,26 +4379,37 @@ void RGFW_window_closePtr(RGFW_window* win) {
#ifdef RGFW_EGL
if ((win->src.gfxType & RGFW_gfxEGL) && win->src.ctx.egl) {
- RGFW_window_deleteContext_EGL(win, win->src.ctx.egl);
- win->src.ctx.egl = NULL;
+ RGFW_eglContext* ctx = win->src.ctx.egl;
+ RGFW_window_setContext_EGL(win, NULL);
+ RGFW_deleteContext_EGL(ctx);
}
#endif
#ifdef RGFW_OPENGL
if ((win->src.gfxType & RGFW_gfxNativeOpenGL) && win->src.ctx.native) {
- RGFW_window_deleteContext_OpenGL(win, win->src.ctx.native);
- win->src.ctx.native = NULL;
+ RGFW_glContext* ctx = win->src.ctx.native;
+ RGFW_window_setContext_OpenGL(win, NULL);
+ RGFW_deleteContext_OpenGL(ctx);
}
#endif
RGFW_window_closePlatform(win);
- RGFW_clipboard_switch(NULL);
+ if (_RGFW->root == win) {
+ _RGFW->root = win->next;
+ if (_RGFW->cur == win) _RGFW->cur = NULL;
+ } else if (_RGFW->cur == win) {
+ RGFW_window* cur;
+ for (cur = _RGFW->root; cur->next && cur->next != win; cur = cur->next);
+ _RGFW->cur = cur;
+ }
+
+ if (_RGFW->clipboard != NULL)
+ RGFW_FREE(_RGFW->clipboard);
+ _RGFW->clipboard = NULL;
_RGFW->windowCount--;
RGFW_debugCallback(RGFW_typeInfo, RGFW_infoWindow, "a window was freed");
-
- if (_RGFW->windowCount == 0 && !(win->internal.flags & RGFW_noDeinitOnClose)) RGFW_deinit();
}
void RGFW_setQueueEvents(RGFW_bool queue) { _RGFW->queueEvents = RGFW_BOOL(queue); }
@@ -4210,6 +4589,7 @@ RGFW_event* RGFW_window_eventQueuePop(RGFW_window* win) {
}
if (ev->common.win != win && ev->common.win != NULL) {
+ RGFW_eventQueuePush(ev);
return NULL;
}
@@ -4219,10 +4599,6 @@ RGFW_event* RGFW_window_eventQueuePop(RGFW_window* win) {
void RGFW_setRootWindow(RGFW_window* win) { _RGFW->root = win; }
RGFW_window* RGFW_getRootWindow(void) { return _RGFW->root; }
-#ifndef RGFW_EGL
-RGFW_bool RGFW_loadEGL(void) { return RGFW_FALSE; }
-#endif
-
void RGFW_window_setFlagsInternal(RGFW_window* win, RGFW_windowFlags flags, RGFW_windowFlags cmpFlags) {
if (flags & RGFW_windowNoBorder) RGFW_window_setBorder(win, 0);
else if (cmpFlags & RGFW_windowNoBorder) RGFW_window_setBorder(win, 1);
@@ -4232,8 +4608,10 @@ void RGFW_window_setFlagsInternal(RGFW_window* win, RGFW_windowFlags flags, RGFW
else if (cmpFlags & RGFW_windowMinimize) RGFW_window_restore(win);
if (flags & RGFW_windowCenter) RGFW_window_center(win);
if (flags & RGFW_windowCenterCursor) RGFW_window_moveMouse(win, win->x + (win->w / 2), win->y + (win->h / 2));
- if (flags & RGFW_windowFullscreen) RGFW_window_setFullscreen(win, RGFW_TRUE);
- else if (cmpFlags & RGFW_windowFullscreen) RGFW_window_setFullscreen(win, 0);
+ if (flags & RGFW_windowFullscreenExclusive) RGFW_window_setFullscreen(win, RGFW_fullscreenExclusive);
+ else if (cmpFlags & RGFW_windowFullscreenExclusive) RGFW_window_setFullscreen(win, 0);
+ if (flags & RGFW_windowFullscreenBorderless) RGFW_window_setFullscreen(win, RGFW_fullscreenBorderless);
+ else if (cmpFlags & RGFW_fullscreenBorderless) RGFW_window_setFullscreen(win, 0);
if (flags & RGFW_windowHideMouse) RGFW_window_showMouse(win, 0);
else if (cmpFlags & RGFW_windowHideMouse) RGFW_window_showMouse(win, 1);
if (flags & RGFW_windowHide) RGFW_window_hide(win);
@@ -4269,13 +4647,8 @@ RGFW_bool RGFW_window_isInFocus(RGFW_window* win) {
#endif
}
-void RGFW_setClassName(const char* name) { RGFW_init(); _RGFW->className = name; }
void RGFW_setBuildDND(RGFW_bool state) { _RGFW->dndBuild = state; }
-#ifndef RGFW_X11
-void RGFW_setXInstName(const char* name) { RGFW_UNUSED(name); }
-#endif
-
RGFW_bool RGFW_window_getMouse(RGFW_window* win, i32* x, i32* y) {
RGFW_ASSERT(win != NULL);
if (x) *x = win->internal.lastMouseX;
@@ -4301,6 +4674,7 @@ u64 RGFW_window_getWindow_X11(RGFW_window* win) { RGFW_UNUSED(win); return 0; }
#ifndef RGFW_WAYLAND
struct wl_display* RGFW_getDisplay_Wayland(void) { return NULL; }
struct wl_surface* RGFW_window_getWindow_Wayland(RGFW_window* win) { RGFW_UNUSED(win); return NULL; }
+RGFW_bool RGFW_usingWayland(void) { return RGFW_FALSE; }
#endif
#ifndef RGFW_WINDOWS
@@ -4329,12 +4703,19 @@ void RGFW_window_center(RGFW_window* win) {
}
RGFW_bool RGFW_monitor_scaleToWindow(RGFW_monitor* mon, RGFW_window* win) {
- RGFW_monitorMode mode;
RGFW_ASSERT(win != NULL);
+ RGFW_ASSERT(mon != NULL);
+ RGFW_monitorMode mode = mon->mode;
mode.w = win->w;
mode.h = win->h;
RGFW_bool ret = RGFW_monitor_requestMode(mon, &mode, RGFW_monitorScale);
+ if (ret == RGFW_FALSE) {
+ RGFW_monitorMode closest;
+ ret = RGFW_monitor_findClosestMode(mon, &mode, &closest);
+ if (ret == RGFW_FALSE) { return ret; }
+ ret = RGFW_monitor_setMode(mon, &closest);
+ }
/* move window to monitor origin so it doesn't move to the next monitor */
RGFW_window_move(win, mon->x, mon->y);
@@ -4374,13 +4755,14 @@ void RGFW_window_setShouldClose(RGFW_window* win, RGFW_bool shouldClose) {
void RGFW_window_scaleToMonitor(RGFW_window* win) {
RGFW_monitor* monitor = RGFW_window_getMonitor(win);
- if (monitor->scaleX == 0 && monitor->scaleY == 0)
+ if (monitor == NULL || (monitor->scaleX == 0 && monitor->scaleY == 0))
return;
RGFW_window_resize(win, (i32)(monitor->scaleX * (float)win->w), (i32)(monitor->scaleY * (float)win->h));
}
void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor* m) {
+ RGFW_ASSERT(m != NULL);
RGFW_window_move(win, m->x + win->x, m->y + win->y);
}
@@ -4478,14 +4860,22 @@ void RGFW_copyImageData64(u8* dest_data, i32 dest_w, i32 dest_h, RGFW_format des
RGFW_monitorNode* RGFW_monitors_add(const RGFW_monitor* mon) {
RGFW_monitorNode* node = NULL;
- if (_RGFW->monitors.freeList.head == NULL) return node;
- node = _RGFW->monitors.freeList.head;
-
- _RGFW->monitors.freeList.head = node->next;
- if (_RGFW->monitors.freeList.head == NULL) {
- _RGFW->monitors.freeList.cur = NULL;
+ #if (RGFW_PREALLOCATED_MONITORS)
+ node = _RGFW->monitors.freeList.head;
+ if (node) {
+ _RGFW->monitors.freeList.head = node->next;
+ if (_RGFW->monitors.freeList.head == NULL) {
+ _RGFW->monitors.freeList.cur = NULL;
+ }
+ } else
+ #elif !defined(RGFW_NO_ALLOCATE_MONITORS)
+ {
+ node = (RGFW_monitorNode*)RGFW_ALLOC(sizeof(RGFW_monitorNode));
}
+ #endif
+
+ if (node == NULL) return NULL;
node->next = NULL;
@@ -4508,23 +4898,34 @@ RGFW_monitorNode* RGFW_monitors_add(const RGFW_monitor* mon) {
void RGFW_monitors_remove(RGFW_monitorNode* node, RGFW_monitorNode* prev) {
_RGFW->monitors.count -= 1;
+ RGFW_monitorNode_free(node);
+
/* remove node from the list */
if (prev != node) {
prev->next = node->next;
} else { /* node is the head */
- _RGFW->monitors.list.head = NULL;
+ _RGFW->monitors.list.head = node->next;
}
node->next = NULL;
- /* move node to the free list */
- if (_RGFW->monitors.freeList.head == NULL) {
- _RGFW->monitors.freeList.head = node;
- } else {
- _RGFW->monitors.freeList.cur->next = node;
- }
+ #if (RGFW_PREALLOCATED_MONITORS)
+ /* check if the monitor was allocated in the heap or not */
+ if (node >= _RGFW->monitors.data && node <= &_RGFW->monitors.data[RGFW_PREALLOCATED_MONITORS - 1]) {
+ /* move node to the free list */
+ if (_RGFW->monitors.freeList.head == NULL) {
+ _RGFW->monitors.freeList.head = node;
+ } else {
+ _RGFW->monitors.freeList.cur->next = node;
+ }
- _RGFW->monitors.freeList.cur = node;
+ _RGFW->monitors.freeList.cur = node;
+ } else
+ {
+ #elif !defined(RGFW_NO_ALLOCATE_MONITORS)
+ RGFW_FREE(node);
+ #endif
+ }
}
void RGFW_monitors_refresh(void) {
@@ -4538,7 +4939,17 @@ void RGFW_monitors_refresh(void) {
}
}
+void RGFW_freeMonitors(void) {
+ RGFW_monitorNode* node = _RGFW->monitors.list.head;
+ while (node != NULL) {
+ RGFW_monitorNode* next = node->next;
+ RGFW_monitors_remove(node, node);
+ node = next;
+ }
+}
+
RGFW_monitorMode* RGFW_monitor_getModes(RGFW_monitor* monitor, size_t* count) {
+ RGFW_ASSERT(monitor != NULL);
size_t num = RGFW_monitor_getModesPtr(monitor, NULL);
RGFW_monitorMode* modes = (RGFW_monitorMode*)RGFW_ALLOC(num * sizeof(RGFW_monitorNode));
num = RGFW_monitor_getModesPtr(monitor, &modes);
@@ -4552,36 +4963,50 @@ void RGFW_freeModes(RGFW_monitorMode* modes) {
}
RGFW_bool RGFW_monitor_findClosestMode(RGFW_monitor* monitor, RGFW_monitorMode* mode, RGFW_monitorMode* closest) {
+ RGFW_ASSERT(monitor != NULL);
size_t count = RGFW_monitor_getModesPtr(monitor, NULL);
RGFW_monitorMode* modes = (RGFW_monitorMode*)RGFW_ALLOC(count * sizeof(RGFW_monitorNode));
count = RGFW_monitor_getModesPtr(monitor, &modes);
RGFW_monitorMode* chosen = NULL;
+ u32 sizeScore = UINT_MAX;
+ u32 rateScore = UINT_MAX;
+ u32 colorScore = UINT_MAX;
- u32 topScore = 1;
for (size_t i = 0; i < count; i++) {
RGFW_monitorMode* mode2 = &modes[i];
- u32 score = 0;
- if (mode->w == mode2->w && mode->h == mode2->h) score += 1000;
- if (mode->red == mode2->red && mode->green == mode2->green && mode->blue == mode2->blue) score += 100;
- if (mode->refreshRate == mode->refreshRate) score += 10;
+ u32 currColorScore = 0;
+ if (mode->red) currColorScore += (u32)RGFW_ABS(mode2->red - mode->red);
+ if (mode->blue) currColorScore += (u32)RGFW_ABS(mode2->green - mode->green);
+ if (mode->green) currColorScore += (u32)RGFW_ABS(mode2->blue - mode->blue);
- if (score > topScore) {
- topScore = score;
- chosen = mode2;
- }
+ u32 currSizeScore = (u32)RGFW_ABS((mode2->w - mode->w) * (mode2->w- mode->w) +
+ (mode2->h - mode->h) * (mode2->h - mode->h));
+
+
+ u32 currRateScore = UINT_MAX - (u32)mode2->refreshRate;
+ currRateScore = (u32)RGFW_ABS(mode2->refreshRate - mode->refreshRate);
+
+ if ((currColorScore < colorScore) ||
+ (currColorScore == colorScore && currSizeScore < sizeScore) ||
+ (currColorScore == colorScore && currSizeScore == sizeScore && currRateScore < rateScore)) {
+ sizeScore = currSizeScore;
+ rateScore = currRateScore;
+ colorScore = currColorScore;
+ chosen = mode2;
+ }
}
if (chosen && closest) *closest = *chosen;
-
RGFW_FREE(modes);
return (chosen == NULL) ? RGFW_FALSE : RGFW_TRUE;
}
RGFW_bool RGFW_monitor_getPosition(RGFW_monitor* monitor, i32* x, i32* y) {
+ RGFW_ASSERT(monitor != NULL);
if (x) *x = monitor->x;
if (y) *y = monitor->y;
return RGFW_TRUE;
@@ -4592,31 +5017,37 @@ const char* RGFW_monitor_getName(RGFW_monitor* monitor) {
}
RGFW_bool RGFW_monitor_getScale(RGFW_monitor* monitor, float* x, float* y) {
+ RGFW_ASSERT(monitor != NULL);
if (x) *x = monitor->scaleX;
if (y) *y = monitor->scaleY;
return RGFW_TRUE;
}
RGFW_bool RGFW_monitor_getPhysicalSize(RGFW_monitor* monitor, float* w, float* h) {
+ RGFW_ASSERT(monitor != NULL);
if (w) *w = monitor->physW;
if (h) *h = monitor->physH;
return RGFW_TRUE;
}
void RGFW_monitor_setUserPtr(RGFW_monitor* monitor, void* userPtr) {
+ RGFW_ASSERT(monitor != NULL);
monitor->userPtr = userPtr;
}
void* RGFW_monitor_getUserPtr(RGFW_monitor* monitor) {
+ RGFW_ASSERT(monitor != NULL);
return monitor->userPtr;
}
RGFW_bool RGFW_monitor_getMode(RGFW_monitor* monitor, RGFW_monitorMode* mode) {
+ RGFW_ASSERT(monitor != NULL);
if (mode) *mode = monitor->mode;
return RGFW_TRUE;
}
RGFW_gammaRamp* RGFW_monitor_getGammaRamp(RGFW_monitor* monitor) {
+ RGFW_ASSERT(monitor != NULL);
RGFW_gammaRamp* ramp = (RGFW_gammaRamp*)RGFW_ALLOC(sizeof(RGFW_gammaRamp));
ramp->count = RGFW_monitor_getGammaRampPtr(monitor, NULL);
ramp->red = (u16*)RGFW_ALLOC(sizeof(u16) * ramp->count);
@@ -4659,6 +5090,7 @@ RGFW_bool RGFW_monitor_setGammaPtr(RGFW_monitor* monitor, float gamma, u16* ptr,
}
RGFW_bool RGFW_monitor_setGamma(RGFW_monitor* monitor, float gamma) {
+ RGFW_ASSERT(monitor != NULL);
size_t count = RGFW_monitor_getGammaRampPtr(monitor, NULL);
u16* ptr = (u16*)RGFW_ALLOC(count * sizeof(u16));
@@ -4669,23 +5101,50 @@ RGFW_bool RGFW_monitor_setGamma(RGFW_monitor* monitor, float gamma) {
}
RGFW_monitor** RGFW_getMonitors(size_t* len) {
- static RGFW_monitor* monitors[RGFW_MAX_MONITORS];
- RGFW_init();
+ if (len != NULL) *len = 0;
+
+ size_t count = 0;
+ if (RGFW_getMonitorsPtr(0, NULL, &count) == RGFW_FALSE || count == 0) return NULL;
+
+ RGFW_monitor** monitors = (RGFW_monitor**)RGFW_ALLOC(sizeof(RGFW_monitor*) * count);
+
+ if (RGFW_getMonitorsPtr(count, monitors, &count) == RGFW_FALSE) {
+ RGFW_FREE(monitors);
+ return NULL;
+ }
+
+ if (len != NULL) *len = count;
+
+ return monitors;
+}
+
+RGFW_bool RGFW_getMonitorsPtr(size_t max, RGFW_monitor** monitors, size_t* len) {
+ RGFW_ASSERT(monitors != NULL);
+ RGFW_ASSERT(_RGFW && "An RGFW context must be initialized using RGFW_init and/or set with RGFW_setInfo");
if (len != NULL) {
*len = _RGFW->monitors.count;
}
- u8 i = 0;
+ if (monitors == NULL || max == 0) return RGFW_TRUE;
+
+
+ if (len != NULL) {
+ *len = max;
+ }
+
+ size_t i = 0;
RGFW_monitorNode* cur_node = _RGFW->monitors.list.head;
- while (cur_node != NULL) {
+ while (cur_node != NULL && i < max) {
monitors[i] = &cur_node->mon;
i++;
cur_node = cur_node->next;
}
- return monitors;
+
+ return RGFW_TRUE;
}
RGFW_monitor* RGFW_getPrimaryMonitor(void) {
+ RGFW_ASSERT(_RGFW && "An RGFW context must be initialized using RGFW_init and/or set with RGFW_setInfo");
if (_RGFW->monitors.primary == NULL) {
_RGFW->monitors.primary = _RGFW->monitors.list.head;
}
@@ -4754,7 +5213,9 @@ RGFW_bool RGFW_window_borderless(RGFW_window* win) {
return (RGFW_bool)RGFW_BOOL(win->internal.flags & RGFW_windowNoBorder);
}
-RGFW_bool RGFW_window_isFullscreen(RGFW_window* win){ return RGFW_BOOL(win->internal.flags & RGFW_windowFullscreen); }
+RGFW_bool RGFW_window_isFullscreenExclusive(RGFW_window* win){ return RGFW_BOOL(win->internal.flags & RGFW_windowFullscreenExclusive); }
+RGFW_bool RGFW_window_isFullscreenBorderless(RGFW_window* win){ return RGFW_BOOL(win->internal.flags & RGFW_windowFullscreenBorderless); }
+RGFW_bool RGFW_window_isFullscreen(RGFW_window* win){ return RGFW_window_isFullscreenExclusive(win) || RGFW_window_isFullscreenBorderless(win); }
RGFW_bool RGFW_window_allowsDND(RGFW_window* win) { return RGFW_BOOL(win->internal.flags & RGFW_windowAllowDND); }
RGFW_bool RGFW_window_setMouseDefault(RGFW_window* win) {
@@ -4782,14 +5243,6 @@ void RGFW_window_setDND(RGFW_window* win, RGFW_bool allow) {
}
#endif
-#if defined(RGFW_X11) || defined(RGFW_MACOS) || defined(RGFW_WASM) || defined(RGFW_WAYLAND)
-#ifndef __USE_POSIX199309
- #define __USE_POSIX199309
-#endif
-#include <time.h>
-struct timespec;
-#endif
-
#if defined(RGFW_WAYLAND) || defined(RGFW_X11) || defined(RGFW_WINDOWS)
void RGFW_window_showMouse(RGFW_window* win, RGFW_bool show) {
RGFW_window_showMouseFlags(win, show);
@@ -4834,6 +5287,118 @@ u32 RGFW_decodeUTF8(const char* string, size_t* starting_index) {
return codepoint - offsets[count - 1];
}
+void RGFW_window_show(RGFW_window* win) {
+ RGFW_ASSERT(win != NULL);
+ if (win->internal.flags & RGFW_windowFocusOnShow) RGFW_window_focus(win);
+ RGFW_window_showPlatform(win);
+ if ((win->internal.flags & RGFW_windowMaximize)) RGFW_window_maximize(win);
+}
+
+void RGFW_window_restore(RGFW_window* win) {
+ RGFW_ASSERT(win != NULL);
+ RGFW_window_restorePlatform(win);
+ win->internal.flags &= ~(u32)RGFW_windowMaximize;
+ RGFW_window_show(win);
+ RGFW_window_move(win, win->internal.oldX, win->internal.oldY);
+ RGFW_window_resize(win, win->internal.oldW, win->internal.oldH);
+}
+
+void RGFW_window_minimize(RGFW_window* win) {
+ RGFW_ASSERT(win != NULL);
+ RGFW_window_minimizePlatform(win);
+ win->internal.flags &= ~(u32)RGFW_windowMaximize;
+}
+
+void RGFW_window_maximize(RGFW_window* win) {
+ RGFW_ASSERT(win != NULL);
+ win->internal.oldX = win->x;
+ win->internal.oldY = win->y;
+ win->internal.oldW = win->w;
+ win->internal.oldH = win->h;
+ win->internal.flags |= RGFW_windowMaximize;
+ RGFW_window_fetchSize(win, NULL, NULL);
+
+ RGFW_window_maximizePlatform(win);
+}
+
+void RGFW_window_move(RGFW_window* win, i32 x, i32 y) {
+ RGFW_ASSERT(win != NULL);
+ win->x = x;
+ win->y = y;
+ RGFW_window_movePlatform(win, x, y);
+ win->internal.flags &= ~(u32)RGFW_windowMaximize;
+}
+
+void RGFW_window_resize(RGFW_window* win, i32 w, i32 h) {
+ RGFW_ASSERT(win != NULL);
+ win->w = w;
+ win->h = h;
+ RGFW_window_resizePlatform(win, w, h);
+ win->internal.flags &= ~(u32)RGFW_windowMaximize;
+}
+
+void RGFW_window_setFullscreen(RGFW_window* win, RGFW_fullscreenMode fullscreen) {
+ RGFW_ASSERT(win != NULL);
+ if ((fullscreen == RGFW_fullscreenExclusive && (win->internal.flags & RGFW_windowFullscreenExclusive)) ||
+ (fullscreen == RGFW_fullscreenBorderless && RGFW_BOOL(win->internal.flags & RGFW_windowFullscreenBorderless)) ||
+ (fullscreen == 0 && RGFW_window_isFullscreen(win) == RGFW_FALSE)) {
+ return;
+ }
+
+ if ((fullscreen == RGFW_fullscreenExclusive && RGFW_BOOL(win->internal.flags & RGFW_windowFullscreenBorderless)) ||
+ (fullscreen == RGFW_fullscreenBorderless && (win->internal.flags & RGFW_windowFullscreenExclusive))) {
+ RGFW_window_setFullscreen(win, RGFW_fullscreenNone);
+ }
+
+ if (fullscreen) {
+ win->internal.oldX = win->x;
+ win->internal.oldY = win->y;
+ win->internal.oldW = win->w;
+ win->internal.oldH = win->h;
+
+ win->internal.oldBorderless = RGFW_window_borderless(win);
+ RGFW_window_setBorder(win, 0);
+
+ RGFW_monitor* mon = RGFW_window_getMonitor(win);
+ RGFW_window_move(win, mon->x, mon->y);
+
+ if (fullscreen == RGFW_fullscreenExclusive) {
+ win->internal.oldMode = mon->mode;
+ RGFW_monitor_scaleToWindow(mon, win);
+ win->internal.monitor = mon;
+ win->internal.newMode = mon->mode;
+ win->internal.flags |= RGFW_windowFullscreenExclusive;
+ } else {
+ win->internal.flags |= RGFW_windowFullscreenBorderless;
+ win->internal.monitor = NULL;
+ }
+
+ RGFW_window_resize(win, mon->mode.w, mon->mode.h);
+ }
+
+ RGFW_window_setFullscreenPlatform(win, (fullscreen > 0) ? RGFW_TRUE : RGFW_FALSE);
+
+ if (fullscreen == 0) {
+ if (win->internal.monitor != NULL) {
+ RGFW_monitor_setMode(win->internal.monitor, &win->internal.oldMode);
+ }
+
+ RGFW_window_setBorder(win, !win->internal.oldBorderless);
+
+ RGFW_window_move(win, win->internal.oldX, win->internal.oldY);
+ RGFW_window_resize(win, win->internal.oldW, win->internal.oldH);
+
+ win->internal.flags &= ~(u32)RGFW_windowFullscreenExclusive;
+ win->internal.flags &= ~(u32)RGFW_windowFullscreenBorderless;
+
+ win->x = win->internal.oldX;
+ win->y = win->internal.oldY;
+ win->w = win->internal.oldW;
+ win->h = win->internal.oldH;
+ return;
+ }
+}
+
/*
graphics API specific code (end of generic code)
starts here
@@ -4844,7 +5409,8 @@ u32 RGFW_decodeUTF8(const char* string, size_t* starting_index) {
OpenGL defines start here (Normal, EGL, OSMesa)
*/
-#if defined(RGFW_OPENGL)
+#if defined(RGFW_OPENGL) || defined(RGFW_EGL)
+
/* EGL, OpenGL */
#define RGFW_DEFAULT_GL_HINTS { \
/* Stencil */ 0, \
@@ -4885,7 +5451,10 @@ void RGFW_resetGlobalHints_OpenGL(void) {
#endif
}
void RGFW_setGlobalHints_OpenGL(RGFW_glHints* hints) { RGFW_globalHints_OpenGL = hints; }
-RGFW_glHints* RGFW_getGlobalHints_OpenGL(void) { RGFW_init(); return RGFW_globalHints_OpenGL; }
+RGFW_glHints* RGFW_getGlobalHints_OpenGL(void) {
+ RGFW_ASSERT(_RGFW && "An RGFW context must be initialized using RGFW_init and/or set with RGFW_setInfo");
+ return RGFW_globalHints_OpenGL;
+}
void* RGFW_glContext_getSourceContext(RGFW_glContext* ctx) {
@@ -4902,30 +5471,15 @@ void* RGFW_glContext_getSourceContext(RGFW_glContext* ctx) {
#endif
}
-RGFW_glContext* RGFW_window_createContext_OpenGL(RGFW_window* win, RGFW_glHints* hints) {
- #ifdef RGFW_WAYLAND
- if (RGFW_usingWayland()) {
- return (RGFW_glContext*)RGFW_window_createContext_EGL(win, hints);
- }
- #endif
- RGFW_glContext* ctx = (RGFW_glContext*)RGFW_ALLOC(sizeof(RGFW_glContext));
- if (RGFW_window_createContextPtr_OpenGL(win, ctx, hints) == RGFW_FALSE) {
- RGFW_FREE(ctx);
- win->src.ctx.native = NULL;
- return NULL;
- }
- win->src.gfxType |= RGFW_gfxOwnedByRGFW;
- return ctx;
-}
-
-RGFW_glContext* RGFW_window_getContext_OpenGL(RGFW_window* win) {
- if (win->src.gfxType & RGFW_windowEGL) return NULL;
- return win->src.ctx.native;
+void RGFW_attribStack_init(RGFW_attribStack* stack, i32* attribs, size_t max) { stack->attribs = attribs; stack->count = 0; stack->max = max; }
+void RGFW_attribStack_pushAttrib(RGFW_attribStack* stack, i32 attrib) {
+ RGFW_ASSERT(stack->count < stack->max);
+ stack->attribs[stack->count] = attrib;
+ stack->count += 1;
}
-
-void RGFW_window_deleteContext_OpenGL(RGFW_window* win, RGFW_glContext* ctx) {
- RGFW_window_deleteContextPtr_OpenGL(win, ctx);
- if (win->src.gfxType & RGFW_gfxOwnedByRGFW) RGFW_FREE(ctx);
+void RGFW_attribStack_pushAttribs(RGFW_attribStack* stack, i32 attrib1, i32 attrib2) {
+ RGFW_attribStack_pushAttrib(stack, attrib1);
+ RGFW_attribStack_pushAttrib(stack, attrib2);
}
RGFW_bool RGFW_extensionSupportedStr(const char* extensions, const char* ext, size_t len) {
@@ -4954,16 +5508,16 @@ RGFW_bool RGFW_extensionSupportedStr(const char* extensions, const char* ext, si
return RGFW_FALSE;
}
-RGFWDEF RGFW_bool RGFW_extensionSupported_base(const char* extension, size_t len);
-RGFW_bool RGFW_extensionSupported_base(const char* extension, size_t len) {
+RGFWDEF RGFW_bool RGFW_extensionSupported_base(const char* extension, size_t len, RGFW_proc (*getProcAddress)(const char* procname));
+RGFW_bool RGFW_extensionSupported_base(const char* extension, size_t len, RGFW_proc (*getProcAddress)(const char* procname)) {
#ifdef GL_NUM_EXTENSIONS
if (RGFW_globalHints_OpenGL->major >= 3) {
i32 i;
GLint count = 0;
- RGFW_proc RGFW_glGetStringi = RGFW_getProcAddress_OpenGL("glGetStringi");
- RGFW_proc RGFW_glGetIntegerv = RGFW_getProcAddress_OpenGL("glGetIntegerv");
+ RGFW_proc RGFW_glGetStringi = getProcAddress("glGetStringi");
+ RGFW_proc RGFW_glGetIntegerv = getProcAddress("glGetIntegerv");
if (RGFW_glGetIntegerv)
((void(*)(GLenum, GLint*))RGFW_glGetIntegerv)(GL_NUM_EXTENSIONS, &count);
@@ -4976,7 +5530,7 @@ RGFW_bool RGFW_extensionSupported_base(const char* extension, size_t len) {
} else
#endif
{
- RGFW_proc RGFW_glGetString = RGFW_getProcAddress_OpenGL("glGetString");
+ RGFW_proc RGFW_glGetString = getProcAddress("glGetString");
#define RGFW_GL_EXTENSIONS 0x1F03
if (RGFW_glGetString) {
const char* extensions = ((const char*(*)(u32))RGFW_glGetString)(RGFW_GL_EXTENSIONS);
@@ -4989,8 +5543,64 @@ RGFW_bool RGFW_extensionSupported_base(const char* extension, size_t len) {
return RGFW_FALSE;
}
+#endif /* OpenGL or EGL */
+
+#ifdef RGFW_OPENGL
+
+void RGFW_unloadGL(void) {
+ if (!_RGFW->nativeGL_handle) return;
+ #ifdef RGFW_WINDOWS
+ FreeLibrary((HMODULE)_RGFW->nativeGL_handle);
+ #elif defined(RGFW_UNIX)
+ dlclose(_RGFW->nativeGL_handle);
+ #endif /* OSX doesn't need it's handle freed */
+
+ _RGFW->nativeGL_handle = NULL;
+ _RGFW->glGetProcAddress = NULL;
+}
+
+RGFW_glContext* RGFW_createContext_OpenGL(RGFW_glHints* hints) {
+ #ifdef RGFW_WAYLAND
+ if (RGFW_usingWayland()) {
+ return (RGFW_glContext*)RGFW_createContext_EGL(hints);
+ }
+ #endif
+ RGFW_glContext* ctx = (RGFW_glContext*)RGFW_ALLOC(sizeof(RGFW_glContext));
+ if (RGFW_createContextPtr_OpenGL(ctx, hints) == RGFW_FALSE) {
+ RGFW_FREE(ctx);
+ return NULL;
+ }
+ return ctx;
+}
+
+RGFW_glContext* RGFW_window_getContext_OpenGL(RGFW_window* win) {
+ if (win->src.gfxType & RGFW_windowEGL) return NULL;
+ return win->src.ctx.native;
+}
+
+void RGFW_deleteContext_OpenGL(RGFW_glContext* ctx) {
+ RGFW_deleteContextPtr_OpenGL(ctx);
+ RGFW_FREE(ctx);
+}
+
+RGFW_glContext* RGFW_copyContext_OpenGL(RGFW_glContext* ctx) {
+ RGFW_glContext* newCtx = (RGFW_glContext*)RGFW_ALLOC(sizeof(RGFW_glContext));
+ RGFW_copyContextPtr_OpenGL(ctx, newCtx);
+ return newCtx;
+}
+
+RGFW_bool RGFW_copyContextPtr_OpenGL(RGFW_glContext* ctx, RGFW_glContext* newCtx) {
+ RGFW_ASSERT(ctx); RGFW_ASSERT(newCtx);
+ RGFW_MEMCPY(newCtx, ctx, sizeof(RGFW_glContext));
+
+#ifdef RGFW_MACOS
+ RGFW_copyContext_OSX_OpenGL(ctx, newCtx);
+#endif
+ return RGFW_TRUE;
+}
+
RGFW_bool RGFW_extensionSupported_OpenGL(const char* extension, size_t len) {
- if (RGFW_extensionSupported_base(extension, len)) return RGFW_TRUE;
+ if (RGFW_extensionSupported_base(extension, len, RGFW_getProcAddress_OpenGL)) return RGFW_TRUE;
return RGFW_extensionSupportedPlatform_OpenGL(extension, len);
}
@@ -5003,16 +5613,7 @@ void RGFW_window_makeCurrentWindow_OpenGL(RGFW_window* win) {
}
RGFW_window* RGFW_getCurrentWindow_OpenGL(void) { return _RGFW->current; }
-void RGFW_attribStack_init(RGFW_attribStack* stack, i32* attribs, size_t max) { stack->attribs = attribs; stack->count = 0; stack->max = max; }
-void RGFW_attribStack_pushAttrib(RGFW_attribStack* stack, i32 attrib) {
- RGFW_ASSERT(stack->count < stack->max);
- stack->attribs[stack->count] = attrib;
- stack->count += 1;
-}
-void RGFW_attribStack_pushAttribs(RGFW_attribStack* stack, i32 attrib1, i32 attrib2) {
- RGFW_attribStack_pushAttrib(stack, attrib1);
- RGFW_attribStack_pushAttrib(stack, attrib2);
-}
+#endif /* OPENGL only */
/* EGL */
#ifdef RGFW_EGL
@@ -5032,33 +5633,25 @@ PFNEGLDESTROYCONTEXTPROC RGFW_eglDestroyContext;
PFNEGLTERMINATEPROC RGFW_eglTerminate;
PFNEGLDESTROYSURFACEPROC RGFW_eglDestroySurface;
PFNEGLGETCURRENTCONTEXTPROC RGFW_eglGetCurrentContext;
-PFNEGLGETPROCADDRESSPROC RGFW_eglGetProcAddress = NULL;
+PFNEGLGETCURRENTSURFACEPROC RGFW_eglGetCurrentSurface;
PFNEGLQUERYSTRINGPROC RGFW_eglQueryString;
PFNEGLGETCONFIGATTRIBPROC RGFW_eglGetConfigAttrib;
#define EGL_SURFACE_MAJOR_VERSION_KHR 0x3098
#define EGL_SURFACE_MINOR_VERSION_KHR 0x30fb
-#ifdef RGFW_WINDOWS
- #include <windows.h>
-#elif defined(RGFW_MACOS) || defined(RGFW_UNIX)
- #include <dlfcn.h>
-#endif
-
#ifdef RGFW_WAYLAND
#include <wayland-egl.h>
#endif
-void* RGFW_eglLibHandle = NULL;
-
void* RGFW_getDisplay_EGL(void) { return _RGFW->EGL_display; }
void* RGFW_eglContext_getSourceContext(RGFW_eglContext* ctx) { return ctx->ctx; }
void* RGFW_eglContext_getSurface(RGFW_eglContext* ctx) { return ctx->surface; }
struct wl_egl_window* RGFW_eglContext_wlEGLWindow(RGFW_eglContext* ctx) { return ctx->eglWindow; }
RGFW_bool RGFW_loadEGL(void) {
- RGFW_init();
- if (RGFW_eglGetProcAddress != NULL) {
+ RGFW_ASSERT(_RGFW && "An RGFW context must be initialized using RGFW_init) and/or set with RGFW_setInfo");
+ if (_RGFW->eglGetProcAddress != NULL) {
return RGFW_TRUE;
}
@@ -5066,7 +5659,7 @@ RGFW_bool RGFW_loadEGL(void) {
#ifdef RGFW_WINDOWS
const char* libNames[] = { "libEGL.dll", "EGL.dll" };
#elif defined(RGFW_MACOS) || defined(RGFW_UNIX)
- /* Linux and macOS */
+ /* unix (including macOS) */
const char* libNames[] = {
"libEGL.so.1", /* most common */
"libEGL.so", /* fallback */
@@ -5076,44 +5669,45 @@ RGFW_bool RGFW_loadEGL(void) {
for (size_t i = 0; i < sizeof(libNames) / sizeof(libNames[0]); i++) {
#ifdef RGFW_WINDOWS
- RGFW_eglLibHandle = (void*)LoadLibraryA(libNames[i]);
- if (RGFW_eglLibHandle) {
- RGFW_eglGetProcAddress = (PFNEGLGETPROCADDRESSPROC)(RGFW_proc)GetProcAddress((HMODULE)RGFW_eglLibHandle, "eglGetProcAddress");
+ _RGFW->EGL_handle = (void*)LoadLibraryA(libNames[i]);
+ if (_RGFW->EGL_handle) {
+ _RGFW->eglGetProcAddress = (PFNEGLGETPROCADDRESSPROC)(RGFW_proc)GetProcAddress((HMODULE)_RGFW->EGL_handle, "eglGetProcAddress");
break;
}
#elif defined(RGFW_MACOS) || defined(RGFW_UNIX)
- RGFW_eglLibHandle = dlopen(libNames[i], RTLD_LAZY | RTLD_GLOBAL);
- if (RGFW_eglLibHandle) {
- void* lib = dlsym(RGFW_eglLibHandle, "eglGetProcAddress");
- if (lib != NULL) RGFW_MEMCPY(&RGFW_eglGetProcAddress, &lib, sizeof(PFNEGLGETPROCADDRESSPROC));
+ _RGFW->EGL_handle = dlopen(libNames[i], RTLD_LAZY | RTLD_GLOBAL);
+ if (_RGFW->EGL_handle) {
+ void* lib = dlsym(_RGFW->EGL_handle, "eglGetProcAddress");
+ if (lib != NULL) RGFW_MEMCPY(&_RGFW->eglGetProcAddress, &lib, sizeof(PFNEGLGETPROCADDRESSPROC));
break;
}
#endif
}
- if (!RGFW_eglLibHandle || !RGFW_eglGetProcAddress) {
+ if (!_RGFW->EGL_handle || !_RGFW->eglGetProcAddress) {
return RGFW_FALSE;
}
- RGFW_eglInitialize = (PFNEGLINITIALIZEPROC) RGFW_eglGetProcAddress("eglInitialize");
- RGFW_eglGetConfigs = (PFNEGLGETCONFIGSPROC) RGFW_eglGetProcAddress("eglGetConfigs");
- RGFW_eglChooseConfig = (PFNEGLCHOOSECONFIGPROC) RGFW_eglGetProcAddress("eglChooseConfig");
- RGFW_eglCreateWindowSurface = (PFNEGLCREATEWINDOWSURFACEPROC) RGFW_eglGetProcAddress("eglCreateWindowSurface");
- RGFW_eglCreateContext = (PFNEGLCREATECONTEXTPROC) RGFW_eglGetProcAddress("eglCreateContext");
- RGFW_eglMakeCurrent = (PFNEGLMAKECURRENTPROC) RGFW_eglGetProcAddress("eglMakeCurrent");
- RGFW_eglGetDisplay = (PFNEGLGETDISPLAYPROC) RGFW_eglGetProcAddress("eglGetDisplay");
- RGFW_eglSwapBuffers = (PFNEGLSWAPBUFFERSPROC) RGFW_eglGetProcAddress("eglSwapBuffers");
- RGFW_eglSwapInterval = (PFNEGLSWAPINTERVALPROC) RGFW_eglGetProcAddress("eglSwapInterval");
- RGFW_eglBindAPI = (PFNEGLBINDAPIPROC) RGFW_eglGetProcAddress("eglBindAPI");
- RGFW_eglDestroyContext = (PFNEGLDESTROYCONTEXTPROC) RGFW_eglGetProcAddress("eglDestroyContext");
- RGFW_eglTerminate = (PFNEGLTERMINATEPROC) RGFW_eglGetProcAddress("eglTerminate");
- RGFW_eglDestroySurface = (PFNEGLDESTROYSURFACEPROC) RGFW_eglGetProcAddress("eglDestroySurface");
- RGFW_eglQueryString = (PFNEGLQUERYSTRINGPROC) RGFW_eglGetProcAddress("eglQueryString");
- RGFW_eglGetCurrentContext = (PFNEGLGETCURRENTCONTEXTPROC) RGFW_eglGetProcAddress("eglGetCurrentContext");
- RGFW_eglGetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC) RGFW_eglGetProcAddress("eglGetConfigAttrib");
+ RGFW_eglInitialize = (PFNEGLINITIALIZEPROC) _RGFW->eglGetProcAddress("eglInitialize");
+ RGFW_eglGetConfigs = (PFNEGLGETCONFIGSPROC) _RGFW->eglGetProcAddress("eglGetConfigs");
+ RGFW_eglChooseConfig = (PFNEGLCHOOSECONFIGPROC) _RGFW->eglGetProcAddress("eglChooseConfig");
+ RGFW_eglCreateWindowSurface = (PFNEGLCREATEWINDOWSURFACEPROC) _RGFW->eglGetProcAddress("eglCreateWindowSurface");
+ RGFW_eglCreateContext = (PFNEGLCREATECONTEXTPROC) _RGFW->eglGetProcAddress("eglCreateContext");
+ RGFW_eglMakeCurrent = (PFNEGLMAKECURRENTPROC) _RGFW->eglGetProcAddress("eglMakeCurrent");
+ RGFW_eglGetDisplay = (PFNEGLGETDISPLAYPROC) _RGFW->eglGetProcAddress("eglGetDisplay");
+ RGFW_eglSwapBuffers = (PFNEGLSWAPBUFFERSPROC) _RGFW->eglGetProcAddress("eglSwapBuffers");
+ RGFW_eglSwapInterval = (PFNEGLSWAPINTERVALPROC) _RGFW->eglGetProcAddress("eglSwapInterval");
+ RGFW_eglBindAPI = (PFNEGLBINDAPIPROC) _RGFW->eglGetProcAddress("eglBindAPI");
+ RGFW_eglDestroyContext = (PFNEGLDESTROYCONTEXTPROC) _RGFW->eglGetProcAddress("eglDestroyContext");
+ RGFW_eglTerminate = (PFNEGLTERMINATEPROC) _RGFW->eglGetProcAddress("eglTerminate");
+ RGFW_eglDestroySurface = (PFNEGLDESTROYSURFACEPROC) _RGFW->eglGetProcAddress("eglDestroySurface");
+ RGFW_eglQueryString = (PFNEGLQUERYSTRINGPROC) _RGFW->eglGetProcAddress("eglQueryString");
+ RGFW_eglGetCurrentContext = (PFNEGLGETCURRENTCONTEXTPROC) _RGFW->eglGetProcAddress("eglGetCurrentContext");
+ RGFW_eglGetCurrentSurface = (PFNEGLGETCURRENTSURFACEPROC) _RGFW->eglGetProcAddress("eglGetCurrentSurface");
+ RGFW_eglGetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC) _RGFW->eglGetProcAddress("eglGetConfigAttrib");
#else
- RGFW_eglGetProcAddress = eglGetProcAddress;
+ _RGFW->eglGetProcAddress = eglGetProcAddress;
RGFW_eglInitialize = (PFNEGLINITIALIZEPROC) eglInitialize;
RGFW_eglGetConfigs = (PFNEGLGETCONFIGSPROC) eglGetConfigs;
RGFW_eglChooseConfig = (PFNEGLCHOOSECONFIGPROC) eglChooseConfig;
@@ -5129,6 +5723,7 @@ RGFW_bool RGFW_loadEGL(void) {
RGFW_eglDestroySurface = (PFNEGLDESTROYSURFACEPROC) eglDestroySurface;
RGFW_eglQueryString = (PFNEGLQUERYSTRINGPROC) eglQueryString;
RGFW_eglGetCurrentContext = (PFNEGLGETCURRENTCONTEXTPROC) eglGetCurrentContext;
+ RGFW_eglGetCurrentSurface = (PFNEGLGETCURRENTSURFACEPROC) eglGetCurrentSurface;
RGFW_eglGetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC)eglGetConfigAttrib;
#endif
@@ -5147,6 +5742,7 @@ RGFW_bool RGFW_loadEGL(void) {
RGFW_eglDestroySurface!= NULL &&
RGFW_eglQueryString != NULL &&
RGFW_eglGetCurrentContext != NULL &&
+ RGFW_eglGetCurrentSurface != NULL &&
RGFW_eglGetConfigAttrib != NULL);
if (out) {
@@ -5155,7 +5751,7 @@ RGFW_bool RGFW_loadEGL(void) {
_RGFW->EGL_display = RGFW_eglGetDisplay((EGLNativeDisplayType) dc);
ReleaseDC(NULL, dc);
#elif defined(RGFW_WAYLAND)
- if (_RGFW->useWaylandBool)
+ if (RGFW_usingWayland() == RGFW_TRUE)
_RGFW->EGL_display = RGFW_eglGetDisplay((EGLNativeDisplayType) _RGFW->wl_display);
else
#endif
@@ -5175,28 +5771,19 @@ RGFW_bool RGFW_loadEGL(void) {
void RGFW_unloadEGL(void) {
- if (!RGFW_eglLibHandle) return;
+ if (!_RGFW->EGL_handle) return;
RGFW_eglTerminate(_RGFW->EGL_display);
#ifdef RGFW_WINDOWS
- FreeLibrary((HMODULE)RGFW_eglLibHandle);
+ FreeLibrary((HMODULE)_RGFW->EGL_handle);
#elif defined(RGFW_MACOS) || defined(RGFW_UNIX)
- dlclose(RGFW_eglLibHandle);
+ dlclose(_RGFW->EGL_handle);
#endif
- RGFW_eglLibHandle = NULL;
- RGFW_eglGetProcAddress = NULL;
+ _RGFW->EGL_handle = NULL;
+ _RGFW->eglGetProcAddress = NULL;
}
-RGFW_bool RGFW_window_createContextPtr_EGL(RGFW_window* win, RGFW_eglContext* ctx, RGFW_glHints* hints) {
- if (RGFW_loadEGL() == RGFW_FALSE) return RGFW_FALSE;
- win->src.ctx.egl = ctx;
- win->src.gfxType = RGFW_gfxEGL;
-
-#ifdef RGFW_WAYLAND
- if (_RGFW->useWaylandBool)
- win->src.ctx.egl->eglWindow = wl_egl_window_create(win->src.surface, win->w, win->h);
-#endif
-
+RGFW_bool RGFW_createContextPtr_EGL(RGFW_eglContext* ctx, RGFW_glHints* hints) {
#ifndef EGL_OPENGL_ES1_BIT
#define EGL_OPENGL_ES1_BIT 0x1
#endif
@@ -5243,8 +5830,13 @@ RGFW_bool RGFW_window_createContextPtr_EGL(RGFW_window* win, RGFW_eglContext* ct
RGFW_eglChooseConfig(_RGFW->EGL_display, egl_config, configs, numConfigs, &numConfigs);
+ if (hints->profile == RGFW_glES)
+ RGFW_eglBindAPI(EGL_OPENGL_ES_API);
+ else
+ RGFW_eglBindAPI(EGL_OPENGL_API);
+
#ifdef RGFW_X11
- RGFW_bool transparent = (win->internal.flags & RGFW_windowTransparent);
+ RGFW_bool transparent = (hints->depth == 32);
EGLint best_depth = 0;
#endif
@@ -5258,7 +5850,7 @@ RGFW_bool RGFW_window_createContextPtr_EGL(RGFW_window* win, RGFW_eglContext* ct
if (best_config == -1) best_config = i;
#ifdef RGFW_X11
- if (_RGFW->useWaylandBool == RGFW_FALSE) {
+ if (RGFW_usingWayland() == RGFW_FALSE) {
XVisualInfo vinfo_template;
vinfo_template.visualid = (VisualID)visual_id;
@@ -5287,15 +5879,101 @@ RGFW_bool RGFW_window_createContextPtr_EGL(RGFW_window* win, RGFW_eglContext* ct
}
EGLConfig config = configs[best_config];
+ ctx->config = config;
+
RGFW_FREE(configs);
+
+ EGLint attribs[20];
+ {
+ RGFW_attribStack stack;
+ RGFW_attribStack_init(&stack, attribs, 20);
+
+ if (hints->major || hints->minor) {
+ RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_MAJOR_VERSION, hints->major);
+ RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_MINOR_VERSION, hints->minor);
+ }
+
+ if (hints->profile == RGFW_glCore) {
+ RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT);
+ } else if (hints->profile == RGFW_glCompatibility) {
+ RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT);
+ } else if (hints->profile == RGFW_glForwardCompatibility) {
+ RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE, EGL_TRUE);
+ }
+
+
+ RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_OPENGL_ROBUST_ACCESS, hints->robustness);
+ RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_OPENGL_DEBUG, hints->debug);
+
+ #ifndef EGL_CONTEXT_RELEASE_BEHAVIOR_KHR
+ #define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097
+ #endif
+
+ #ifndef EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR
+ #define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
+ #endif
+
+ if (hints->releaseBehavior == RGFW_glReleaseFlush) {
+ RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_RELEASE_BEHAVIOR_KHR, EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
+ } else {
+ RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_RELEASE_BEHAVIOR_KHR, 0x0000);
+ }
+
+ RGFW_attribStack_pushAttribs(&stack, EGL_NONE, EGL_NONE);
+ }
+
+ ctx->ctx = RGFW_eglCreateContext(_RGFW->EGL_display, config, hints->shareEGL, attribs);
+ if (ctx->ctx == NULL) {
+ RGFW_attribStack stack;
+ RGFW_attribStack_init(&stack, attribs, 20);
+ RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_CLIENT_VERSION, hints->major);
+ RGFW_attribStack_pushAttribs(&stack, EGL_NONE, EGL_NONE);
+ ctx->ctx = RGFW_eglCreateContext(_RGFW->EGL_display, config, hints->shareEGL, attribs);
+ }
+
+ if (ctx->ctx == NULL) {
+ RGFW_debugCallback(RGFW_typeError, RGFW_errEGLContext, "Failed to create an EGL context.");
+ return RGFW_FALSE;
+ }
+
+ RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "EGL context initalized.");
+ return RGFW_TRUE;
+}
+
+RGFW_bool RGFW_window_setContext_EGL(RGFW_window* win, RGFW_eglContext* ctx) {
+ RGFW_ASSERT(win);
+ if (ctx == NULL && win->src.ctx.egl != NULL) {
+ #ifdef RGFW_WAYLAND
+ if (RGFW_usingWayland() == RGFW_TRUE) {
+ wl_egl_window_destroy(win->src.ctx.egl->eglWindow);
+ }
+ #endif
+
+ win->src.ctx.egl = NULL;
+ RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "EGL window surface freed");
+ return RGFW_TRUE;
+ }
+
+ win->src.ctx.egl = ctx;
+ win->src.gfxType = RGFW_gfxEGL;
+
+#ifdef RGFW_WAYLAND
+ if (RGFW_usingWayland() == RGFW_TRUE)
+ win->src.ctx.egl->eglWindow = wl_egl_window_create(win->src.surface, win->w, win->h);
+#endif
+
+ #ifndef EGL_OPENGL_ES1_BIT
+ #define EGL_OPENGL_ES1_BIT 0x1
+ #endif
+
#ifdef RGFW_X11
- if (_RGFW->useWaylandBool == RGFW_FALSE) {
+ if (RGFW_usingWayland() == RGFW_FALSE) {
/* This is required so that way the user can create their own OpenGL context after RGFW_createWindow is used */
XVisualInfo* result;
XVisualInfo desired;
EGLint visualID = 0, count = 0;
- RGFW_eglGetConfigAttrib(_RGFW->EGL_display, config, EGL_NATIVE_VISUAL_ID, &visualID);
+ RGFW_eglGetConfigAttrib(_RGFW->EGL_display, ctx->config, EGL_NATIVE_VISUAL_ID, &visualID);
if (visualID) {
desired.visualid = (VisualID)visualID;
result = XGetVisualInfo(_RGFW->display, VisualIDMask, &desired, &count);
@@ -5310,12 +5988,18 @@ RGFW_bool RGFW_window_createContextPtr_EGL(RGFW_window* win, RGFW_eglContext* ct
RGFW_debugCallback(RGFW_typeError, RGFW_errEGLContext, "Failed to find a valid visual for the EGL config");
} else {
RGFW_bool showWindow = RGFW_FALSE;
+ char* name = NULL;
if (win->src.window) {
showWindow = (RGFW_window_isMinimized(win) == RGFW_FALSE);
+ name = RGFW_XGetWindowName(win->src.window);
RGFW_window_closePlatform(win);
}
- RGFW_XCreateWindow(*result, "", win->internal.flags, win);
+ if (RGFW_XCreateWindow(*result, name ? name : "", win->internal.flags, win) == RGFW_FALSE) {
+ return RGFW_FALSE;
+ }
+
+ if (name != NULL) XFree(name);
if (showWindow) {
RGFW_window_show(win);
@@ -5325,6 +6009,8 @@ RGFW_bool RGFW_window_createContextPtr_EGL(RGFW_window* win, RGFW_eglContext* ct
}
#endif
+ RGFW_glHints* hints = RGFW_getGlobalHints_OpenGL();
+
EGLint surf_attribs[9];
{
@@ -5366,81 +6052,38 @@ RGFW_bool RGFW_window_createContextPtr_EGL(RGFW_window* win, RGFW_eglContext* ct
RGFW_window_setLayer_OSX(win, layer);
- win->src.ctx.egl->surface = RGFW_eglCreateWindowSurface(_RGFW->EGL_display, config, (EGLNativeWindowType) layer, surf_attribs);
+ win->src.ctx.egl->surface = RGFW_eglCreateWindowSurface(_RGFW->EGL_display, (EGLConfig)ctx->config, (EGLNativeWindowType) layer, surf_attribs);
#elif defined(RGFW_WINDOWS)
- win->src.ctx.egl->surface = RGFW_eglCreateWindowSurface(_RGFW->EGL_display, config, (EGLNativeWindowType) win->src.window, surf_attribs);
+ win->src.ctx.egl->surface = RGFW_eglCreateWindowSurface(_RGFW->EGL_display, (EGLConfig)ctx->config, (EGLNativeWindowType) win->src.window, surf_attribs);
#elif defined(RGFW_WAYLAND)
- if (_RGFW->useWaylandBool)
- win->src.ctx.egl->surface = RGFW_eglCreateWindowSurface(_RGFW->EGL_display, config, (EGLNativeWindowType) win->src.ctx.egl->eglWindow, surf_attribs);
+ if (RGFW_usingWayland() == RGFW_TRUE)
+ win->src.ctx.egl->surface = RGFW_eglCreateWindowSurface(_RGFW->EGL_display, (EGLConfig)ctx->config, (EGLNativeWindowType) win->src.ctx.egl->eglWindow, surf_attribs);
else
#endif
#ifdef RGFW_X11
- win->src.ctx.egl->surface = RGFW_eglCreateWindowSurface(_RGFW->EGL_display, config, (EGLNativeWindowType) win->src.window, surf_attribs);
+ win->src.ctx.egl->surface = RGFW_eglCreateWindowSurface(_RGFW->EGL_display, (EGLConfig)ctx->config, (EGLNativeWindowType) win->src.window, surf_attribs);
#else
{}
#endif
#ifdef RGFW_WASM
- win->src.ctx.egl->surface = eglCreateWindowSurface(_RGFW->EGL_display, config, 0, 0);
+ win->src.ctx.egl->surface = eglCreateWindowSurface(_RGFW->EGL_display, (EGLConfig)ctx->config, 0, 0);
#endif
- if (win->src.ctx.egl->surface == NULL) {
+ if (win->src.ctx.egl->surface == EGL_NO_SURFACE) {
RGFW_debugCallback(RGFW_typeError, RGFW_errEGLContext, "Failed to create an EGL surface.");
return RGFW_FALSE;
}
- EGLint attribs[20];
- {
- RGFW_attribStack stack;
- RGFW_attribStack_init(&stack, attribs, 20);
-
- if (hints->major || hints->minor) {
- RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_MAJOR_VERSION, hints->major);
- RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_MINOR_VERSION, hints->minor);
- }
-
- if (hints->profile == RGFW_glCore) {
- RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT);
- } else if (hints->profile == RGFW_glCompatibility) {
- RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT);
- } else if (hints->profile == RGFW_glForwardCompatibility) {
- RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE, EGL_TRUE);
- }
-
-
- RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_OPENGL_ROBUST_ACCESS, hints->robustness);
- RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_OPENGL_DEBUG, hints->debug);
-
- #ifndef EGL_CONTEXT_RELEASE_BEHAVIOR_KHR
- #define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097
- #endif
-
- #ifndef EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR
- #define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
- #endif
-
- if (hints->releaseBehavior == RGFW_glReleaseFlush) {
- RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_RELEASE_BEHAVIOR_KHR, EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
- } else {
- RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_RELEASE_BEHAVIOR_KHR, 0x0000);
- }
-
- RGFW_attribStack_pushAttribs(&stack, EGL_NONE, EGL_NONE);
- }
-
- if (hints->profile == RGFW_glES)
- RGFW_eglBindAPI(EGL_OPENGL_ES_API);
- else
- RGFW_eglBindAPI(EGL_OPENGL_API);
+ RGFW_eglMakeCurrent(_RGFW->EGL_display, win->src.ctx.egl->surface, win->src.ctx.egl->surface, win->src.ctx.egl->ctx);
+ RGFW_eglSwapBuffers(_RGFW->EGL_display, win->src.ctx.egl->surface);
- win->src.ctx.egl->ctx = RGFW_eglCreateContext(_RGFW->EGL_display, config, hints->shareEGL, attribs);
+ RGFW_window_swapInterval_EGL(win, 0);
- if (win->src.ctx.egl->ctx == NULL) {
- RGFW_debugCallback(RGFW_typeError, RGFW_errEGLContext, "Failed to create an EGL context.");
- return RGFW_FALSE;
- }
+#ifdef RGFW_MACOS
+ /*NOTE: another OpenGL/setFlags related hack, this because OSX the 'view' class must be setup after the NSOpenGL view is made AND after setFlags happens */
+ RGFW_osx_initView(win);
+#endif
- RGFW_eglMakeCurrent(_RGFW->EGL_display, win->src.ctx.egl->surface, win->src.ctx.egl->surface, win->src.ctx.egl->ctx);
- RGFW_eglSwapBuffers(_RGFW->EGL_display, win->src.ctx.egl->surface);
RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "EGL context initalized.");
return RGFW_TRUE;
}
@@ -5450,18 +6093,12 @@ RGFW_eglContext* RGFW_window_getContext_EGL(RGFW_window* win) {
return win->src.ctx.egl;
}
-void RGFW_window_deleteContextPtr_EGL(RGFW_window* win, RGFW_eglContext* ctx) {
+void RGFW_deleteContextPtr_EGL(RGFW_eglContext* ctx) {
if (_RGFW->EGL_display == NULL) return;
RGFW_eglDestroySurface(_RGFW->EGL_display, ctx->surface);
RGFW_eglDestroyContext(_RGFW->EGL_display, ctx->ctx);
RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "EGL context freed");
- #ifdef RGFW_WAYLAND
- if (_RGFW->useWaylandBool == RGFW_FALSE) return;
- wl_egl_window_destroy(win->src.ctx.egl->eglWindow);
- RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "EGL window context freed");
- #endif
- win->src.ctx.egl = NULL;
}
void RGFW_window_makeCurrentContext_EGL(RGFW_window* win) { if (win) RGFW_ASSERT(win->src.ctx.egl);
@@ -5475,37 +6112,52 @@ void RGFW_window_makeCurrentContext_EGL(RGFW_window* win) { if (win) RGFW_ASSERT
void RGFW_window_swapBuffers_EGL(RGFW_window* win) {
if (RGFW_eglSwapBuffers)
RGFW_eglSwapBuffers(_RGFW->EGL_display, win->src.ctx.egl->surface);
+ #ifdef RGFW_OPENGL
else RGFW_window_swapBuffers_OpenGL(win);
+ #endif
}
void* RGFW_getCurrentContext_EGL(void) {
return RGFW_eglGetCurrentContext();
}
+void* RGFW_getCurrentSurface_EGL(void) {
+ return RGFW_eglGetCurrentSurface(EGL_DRAW);
+}
+
RGFW_proc RGFW_getProcAddress_EGL(const char* procname) {
#if defined(RGFW_WINDOWS)
- RGFW_proc proc = (RGFW_proc) GetProcAddress(RGFW_wgl_dll, procname);
+ RGFW_proc proc = (RGFW_proc) GetProcAddress(_RGFW->nativeGL_handle, procname);
if (proc)
return proc;
#endif
- return (RGFW_proc) RGFW_eglGetProcAddress(procname);
+ return (RGFW_proc) _RGFW->eglGetProcAddress(procname);
}
RGFW_bool RGFW_extensionSupportedPlatform_EGL(const char* extension, size_t len) {
- if (RGFW_loadEGL() == RGFW_FALSE) return RGFW_FALSE;
const char* extensions = RGFW_eglQueryString(_RGFW->EGL_display, EGL_EXTENSIONS);
return extensions != NULL && RGFW_extensionSupportedStr(extensions, extension, len);
}
void RGFW_window_swapInterval_EGL(RGFW_window* win, i32 swapInterval) {
RGFW_ASSERT(win != NULL);
+
+ void* ctx = RGFW_eglGetCurrentContext();
+ void* surface = RGFW_eglGetCurrentSurface(EGL_DRAW);
+ if (ctx == win->src.ctx.egl->ctx && surface == win->src.ctx.egl->surface) {
+ RGFW_eglSwapInterval(_RGFW->EGL_display, swapInterval);
+ return;
+ }
+
+ RGFW_eglMakeCurrent(_RGFW->EGL_display, win->src.ctx.egl->surface, win->src.ctx.egl->surface, win->src.ctx.egl->ctx);
RGFW_eglSwapInterval(_RGFW->EGL_display, swapInterval);
+ RGFW_eglMakeCurrent(_RGFW->EGL_display, surface, surface, ctx);
}
RGFW_bool RGFW_extensionSupported_EGL(const char* extension, size_t len) {
- if (RGFW_extensionSupported_base(extension, len)) return RGFW_TRUE;
+ if (RGFW_extensionSupported_base(extension, len, RGFW_getProcAddress_EGL)) return RGFW_TRUE;
return RGFW_extensionSupportedPlatform_EGL(extension, len);
}
@@ -5516,20 +6168,30 @@ void RGFW_window_makeCurrentWindow_EGL(RGFW_window* win) {
RGFW_window* RGFW_getCurrentWindow_EGL(void) { return _RGFW->current; }
-RGFW_eglContext* RGFW_window_createContext_EGL(RGFW_window* win, RGFW_glHints* hints) {
+RGFW_eglContext* RGFW_createContext_EGL(RGFW_glHints* hints) {
RGFW_eglContext* ctx = (RGFW_eglContext*)RGFW_ALLOC(sizeof(RGFW_eglContext));
- if (RGFW_window_createContextPtr_EGL(win, ctx, hints) == RGFW_FALSE) {
+ if (RGFW_createContextPtr_EGL(ctx, hints) == RGFW_FALSE) {
RGFW_FREE(ctx);
- win->src.ctx.egl = NULL;
return NULL;
}
- win->src.gfxType |= RGFW_gfxOwnedByRGFW;
return ctx;
}
-void RGFW_window_deleteContext_EGL(RGFW_window* win, RGFW_eglContext* ctx) {
- RGFW_window_deleteContextPtr_EGL(win, ctx);
- if (win->src.gfxType & RGFW_gfxOwnedByRGFW) RGFW_FREE(ctx);
+void RGFW_deleteContext_EGL(RGFW_eglContext* ctx) {
+ RGFW_deleteContextPtr_EGL(ctx);
+ RGFW_FREE(ctx);
+}
+
+RGFW_eglContext* RGFW_copyContext_EGL(RGFW_eglContext* ctx) {
+ RGFW_eglContext* newCtx = (RGFW_eglContext*)RGFW_ALLOC(sizeof(RGFW_eglContext));
+ RGFW_copyContextPtr_EGL(ctx, newCtx);
+ return newCtx;
+}
+
+RGFW_bool RGFW_copyContextPtr_EGL(RGFW_eglContext* ctx, RGFW_eglContext* newCtx) {
+ RGFW_ASSERT(ctx); RGFW_ASSERT(newCtx);
+ RGFW_MEMCPY(newCtx, ctx, sizeof(RGFW_eglContext));
+ return RGFW_TRUE;
}
#endif /* RGFW_EGL */
@@ -5537,7 +6199,8 @@ void RGFW_window_deleteContext_EGL(RGFW_window* win, RGFW_eglContext* ctx) {
/*
end of RGFW_EGL defines
*/
-#endif /* end of RGFW_GL (OpenGL, EGL, OSMesa )*/
+
+/* end of RGFW_GL (OpenGL, EGL, OSMesa )*/
/*
RGFW_VULKAN defines
@@ -5547,6 +6210,67 @@ void RGFW_window_deleteContext_EGL(RGFW_window* win, RGFW_eglContext* ctx) {
#include <objc/message.h>
#endif
+RGFW_bool RGFW_loadVulkan(void) {
+ if (_RGFW->vulkan_handle) return RGFW_TRUE;
+ const char* names[] = {
+ #ifdef RGFW_WINDOWS
+ "vulkan-1.dll",
+ #endif
+ #ifdef RGFW_MACOS
+ "libvulkan.1.dylib",
+ #endif
+ #ifdef RGFW_UNIX
+ "libvulkan.so.1",
+ "libvulkan.so"
+ #endif
+ };
+
+ for (size_t i = 0; i < sizeof(names) / sizeof(names[0]); i++) {
+ if (_RGFW->vulkan_handle) break;
+ #ifdef RGFW_WINDOWS
+ _RGFW->vulkan_handle = LoadLibraryA(names[i]);
+ #else
+ _RGFW->vulkan_handle = dlopen(names[i], RTLD_LAZY | RTLD_LOCAL);
+ #endif
+ }
+
+ if (!_RGFW->vulkan_handle) {
+ return RGFW_FALSE;
+ }
+
+ #ifdef RGFW_WINDOWS
+ _RGFW->vkGetInstanceProcAddress = (RGFW_proc(*)(void*, const char*))(RGFW_proc)GetProcAddress((HMODULE)_RGFW->vulkan_handle, "vkGetInstanceProcAddr");
+ #else
+ void* lib = dlsym(_RGFW->vulkan_handle, "vkGetInstanceProcAddr");
+ if (lib != NULL) RGFW_MEMCPY(&_RGFW->vkGetInstanceProcAddress, &lib, sizeof(_RGFW->vkGetInstanceProcAddress));
+ #endif
+
+ if (_RGFW->vkGetInstanceProcAddress == NULL) {
+ return RGFW_FALSE;
+ }
+
+
+ return RGFW_TRUE;
+}
+
+#define RGFW_LOAD_VK(func) if (_RGFW->func == NULL) _RGFW->func = (RGFW_##func##Proc)RGFW_getInstanceProcAddress_Vulkan(instance, #func); RGFW_ASSERT(_RGFW->func);
+
+void RGFW_unloadVulkan(void) {
+ if (!_RGFW->vulkan_handle) return;
+ #ifdef RGFW_WINDOWS
+ FreeLibrary((HMODULE)_RGFW->vulkan_handle);
+ #elif defined(RGFW_UNIX)
+ dlclose(_RGFW->vulkan_handle);
+ #endif /* OSX doesn't need it's handle freed */
+
+ _RGFW->vulkan_handle = NULL;
+}
+
+RGFW_proc RGFW_getInstanceProcAddress_Vulkan(VkInstance instance, const char* procname) {
+ RGFW_ASSERT(_RGFW->vkGetInstanceProcAddress);
+ return _RGFW->vkGetInstanceProcAddress(instance, procname);
+}
+
const char** RGFW_getRequiredInstanceExtensions_Vulkan(size_t* count) {
static const char* arr[2] = {VK_KHR_SURFACE_EXTENSION_NAME};
arr[1] = RGFW_VK_SURFACE;
@@ -5559,40 +6283,41 @@ const char** RGFW_getRequiredInstanceExtensions_Vulkan(size_t* count) {
VkResult RGFW_window_createSurface_Vulkan(RGFW_window* win, VkInstance instance, VkSurfaceKHR* surface) {
RGFW_ASSERT(win != NULL); RGFW_ASSERT(instance);
RGFW_ASSERT(surface != NULL);
-
*surface = VK_NULL_HANDLE;
#ifdef RGFW_X11
-
+ RGFW_LOAD_VK(vkCreateXlibSurfaceKHR);
VkXlibSurfaceCreateInfoKHR x11 = { VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, 0, 0, (Display*) _RGFW->display, (Window) win->src.window };
- return vkCreateXlibSurfaceKHR(instance, &x11, NULL, surface);
+ return _RGFW->vkCreateXlibSurfaceKHR(instance, &x11, NULL, surface);
#endif
#if defined(RGFW_WAYLAND)
-
+ RGFW_LOAD_VK(vkCreateWaylandSurfaceKHR);
VkWaylandSurfaceCreateInfoKHR wayland = { VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR, 0, 0, (struct wl_display*) _RGFW->wl_display, (struct wl_surface*) win->src.surface };
- return vkCreateWaylandSurfaceKHR(instance, &wayland, NULL, surface);
+ return _RGFW->vkCreateWaylandSurfaceKHR(instance, &wayland, NULL, surface);
#elif defined(RGFW_WINDOWS)
- VkWin32SurfaceCreateInfoKHR win32 = { VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, 0, 0, GetModuleHandle(NULL), (HWND)win->src.window };
-
- return vkCreateWin32SurfaceKHR(instance, &win32, NULL, surface);
+ RGFW_LOAD_VK(vkCreateWin32SurfaceKHR);
+ VkWin32SurfaceCreateInfoKHR win32 = { VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, 0, 0, _RGFW->instance, (HWND)win->src.window };
+ return _RGFW->vkCreateWin32SurfaceKHR(instance, &win32, NULL, surface);
#endif
}
#endif
-RGFW_bool RGFW_getPresentationSupport_Vulkan(VkPhysicalDevice physicalDevice, u32 queueFamilyIndex) {
- if (_RGFW == NULL) RGFW_init();
-#ifdef RGFW_X11
+RGFW_bool RGFW_getPhysicalDevicePresentationSupport_Vulkan(VkInstance instance, VkPhysicalDevice physicalDevice, u32 queueFamilyIndex) {
+ RGFW_ASSERT(_RGFW && "An RGFW context must be initialized using RGFW_init and/or set with RGFW_setInfo");
+#ifdef RGFW_X11
+ RGFW_LOAD_VK(vkGetPhysicalDeviceXlibPresentationSupportKHR);
Visual* visual = DefaultVisual(_RGFW->display, DefaultScreen(_RGFW->display));
- RGFW_bool out = vkGetPhysicalDeviceXlibPresentationSupportKHR(physicalDevice, queueFamilyIndex, _RGFW->display, XVisualIDFromVisual(visual));
+ RGFW_bool out = _RGFW->vkGetPhysicalDeviceXlibPresentationSupportKHR(physicalDevice, queueFamilyIndex, _RGFW->display, XVisualIDFromVisual(visual));
return out;
#endif
#if defined(RGFW_WAYLAND)
-
- RGFW_bool wlout = vkGetPhysicalDeviceWaylandPresentationSupportKHR(physicalDevice, queueFamilyIndex, _RGFW->wl_display);
+ RGFW_LOAD_VK(vkGetPhysicalDeviceWaylandPresentationSupportKHR);
+ RGFW_bool wlout = _RGFW->vkGetPhysicalDeviceWaylandPresentationSupportKHR(physicalDevice, queueFamilyIndex, _RGFW->wl_display);
return wlout;
#elif defined(RGFW_WINDOWS)
- RGFW_bool out = vkGetPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamilyIndex);
+ RGFW_LOAD_VK(vkGetPhysicalDeviceWin32PresentationSupportKHR);
+ RGFW_bool out = _RGFW->vkGetPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamilyIndex);
return out;
#elif defined(RGFW_MACOS) && !defined(RGFW_MACOS_X11)
RGFW_UNUSED(physicalDevice);
@@ -5600,6 +6325,9 @@ RGFW_bool RGFW_getPresentationSupport_Vulkan(VkPhysicalDevice physicalDevice, u3
return RGFW_FALSE; /* TODO */
#endif
}
+
+
+#undef RGFW_LOAD_VK
#endif /* end of RGFW_vulkan */
/*
@@ -5609,9 +6337,11 @@ This is where OS specific stuff starts
/* start of unix (wayland or X11 (unix) ) defines */
#ifdef RGFW_UNIX
+
#include <fcntl.h>
#include <poll.h>
#include <unistd.h>
+#include <time.h>
void RGFW_stopCheckEvents(void) {
@@ -5624,11 +6354,21 @@ void RGFW_stopCheckEvents(void) {
}
}
-RGFWDEF u64 RGFW_linux_getTimeNS(void);
-u64 RGFW_linux_getTimeNS(void) {
- struct timespec ts;
+RGFWDEF u64 RGFW_unix_getTimeNS(void);
+u64 RGFW_unix_getTimeNS(void) {
+ struct timespec ts;
+ static i32 clock = -1;
+ if (clock == -1) {
+ #if defined(_POSIX_MONOTONIC_CLOCK)
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
+ clock = CLOCK_MONOTONIC;
+ else
+ #endif
+ clock = CLOCK_REALTIME;
+ }
+
const u64 scale_factor = 1000000000;
- clock_gettime(_RGFW->clock, &ts);
+ clock_gettime(clock, &ts);
return (u64)ts.tv_sec * scale_factor + (u64)ts.tv_nsec;
}
@@ -5685,7 +6425,7 @@ void RGFW_waitForEvent(i32 waitMS) {
}
- u64 start = RGFW_linux_getTimeNS();
+ u64 start = RGFW_unix_getTimeNS();
if (RGFW_usingWayland()) {
#ifdef RGFW_WAYLAND
while (wl_display_dispatch_pending(_RGFW->wl_display) == 0) {
@@ -5698,7 +6438,7 @@ void RGFW_waitForEvent(i32 waitMS) {
}
if (waitMS != RGFW_eventWaitNext) {
- waitMS -= (i32)(RGFW_linux_getTimeNS() - start) / (i32)1e+6;
+ waitMS -= (i32)(RGFW_unix_getTimeNS() - start) / (i32)1e+6;
}
}
@@ -5714,7 +6454,7 @@ void RGFW_waitForEvent(i32 waitMS) {
break;
if (waitMS != RGFW_eventWaitNext) {
- waitMS -= (i32)(RGFW_linux_getTimeNS() - start) / (i32)1e+6;
+ waitMS -= (i32)(RGFW_unix_getTimeNS() - start) / (i32)1e+6;
}
}
#endif
@@ -5781,11 +6521,11 @@ char* RGFW_strtok(char* str, const char* delimStr) {
}
#ifdef RGFW_X11
-RGFWDEF i32 RGFW_initPlatform_X11(void);
+RGFWDEF i32 RGFW_initPlatform_X11(const char* className, RGFW_initFlags flags);
RGFWDEF void RGFW_deinitPlatform_X11(void);
#endif
#ifdef RGFW_WAYLAND
-RGFWDEF i32 RGFW_initPlatform_Wayland(void);
+RGFWDEF i32 RGFW_initPlatform_Wayland(const char* className, RGFW_initFlags flags);
RGFWDEF void RGFW_deinitPlatform_Wayland(void);
#endif
@@ -5922,34 +6662,30 @@ void RGFW_initKeycodesPlatform(void) {
_RGFW->keycodes[162] = RGFW_keyWorld2; /* non-US key #2 */
}
-i32 RGFW_initPlatform(void) {
- #if defined(_POSIX_MONOTONIC_CLOCK)
- struct timespec ts;
- RGFW_MEMZERO(&ts, sizeof(struct timespec));
-
- if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
- _RGFW->clock = CLOCK_MONOTONIC;
- #else
- _RGFW->clock = CLOCK_REALTIME;
- #endif
-
+i32 RGFW_initPlatform(const char* className, RGFW_initFlags flags) {
#ifdef RGFW_WAYLAND
- RGFW_load_Wayland();
- i32 ret = RGFW_initPlatform_Wayland();
- if (ret == 0) {
- return 0;
+ if (!(flags & RGFW_initX11)) {
+ _RGFW->useWaylandBool = RGFW_TRUE;
+ RGFW_load_Wayland();
+ i32 ret = RGFW_initPlatform_Wayland(className, flags);
+
+ if (ret == 0) {
+ return 0;
+ } else {
+ #ifdef RGFW_X11
+ RGFW_debugCallback(RGFW_typeWarning, RGFW_warningWayland, "Falling back to X11");
+ _RGFW->useWaylandBool = RGFW_FALSE;
+ #else
+ return ret;
+ #endif
+ }
} else {
- #ifdef RGFW_X11
- RGFW_debugCallback(RGFW_typeWarning, RGFW_warningWayland, "Falling back to X11");
- RGFW_useWayland(0);
- #else
- return ret;
- #endif
+ _RGFW->useWaylandBool = RGFW_FALSE;
}
#endif
#ifdef RGFW_X11
RGFW_load_X11();
- return RGFW_initPlatform_X11();
+ return RGFW_initPlatform_X11(className, flags);
#else
return 0;
#endif
@@ -5962,7 +6698,7 @@ void RGFW_deinitPlatform(void) {
close(_RGFW->eventWait_forceStop[1]);
}
#ifdef RGFW_WAYLAND
- if (_RGFW->useWaylandBool) {
+ if (RGFW_usingWayland()) {
RGFW_deinitPlatform_Wayland();
return;
}
@@ -6034,6 +6770,9 @@ void RGFW_unix_parseURI(RGFW_window* win, char* data) {
}
}
+#if !defined(RGFW_X11) && defined(RGFW_OPENGL)
+RGFW_bool RGFW_loadGL(void) { return RGFW_FALSE; }
+#endif
#endif /* end of wayland or X11 defines */
@@ -6041,7 +6780,7 @@ void RGFW_unix_parseURI(RGFW_window* win, char* data) {
/*
-Start of Linux / Unix defines
+Start of *nix defines
*/
@@ -6053,13 +6792,16 @@ Start of Linux / Unix defines
#define RGFW_FUNC(func) func
#endif
+#ifdef RGFW_X11_DEBUG
+ #define RGFW_X11_CRASH_ON_ERROR
+#endif
+
#include <dlfcn.h>
#include <unistd.h>
#include <limits.h> /* for data limits (mainly used in drag and drop functions) */
#include <poll.h>
-void RGFW_setXInstName(const char* name) { _RGFW->instName = name; }
#if !defined(RGFW_NO_X11_CURSOR) && defined(RGFW_X11)
#include <X11/Xcursor/Xcursor.h>
#endif
@@ -6110,7 +6852,106 @@ void RGFW_setXInstName(const char* name) { _RGFW->instName = name; }
#undef GLsizeiptr
#undef GLboolean
#endif
- typedef GLXContext(*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
+ typedef GLXContext(*RGFW_glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
+ typedef const char* (*RGFW_glXQueryExtensionsStringProc)(Display* dpy, int screen);
+ typedef XVisualInfo* (*RGFW_glXChooseVisualProc)(Display*, int, int*);
+ typedef GLXContext (*RGFW_glXCreateContextProc)(Display*, XVisualInfo*, GLXContext, Bool);
+ typedef Bool (*RGFW_glXMakeCurrentProc)(Display*, GLXDrawable, GLXContext);
+ typedef GLXContext (*RGFW_glXGetCurrentContextProc)(void);
+ typedef GLXContext (*RGFW_glXGetCurrentDrawableProc)(void);
+ typedef void (*RGFW_glXSwapBuffersProc)(Display*, GLXDrawable);
+ typedef PFNGLXSWAPINTERVALEXTPROC RGFW_glXSwapIntervalEXTProc;
+ typedef __GLXextFuncPtr (*RGFW_glXGetProcAddressProc)(const u8*procname);
+ typedef PFNGLXGETVISUALFROMFBCONFIGPROC RGFW_glXGetVisualFromFBConfigProc;
+ typedef PFNGLXGETFBCONFIGATTRIBPROC RGFW_glXGetFBConfigAttribProc;
+ typedef __GLXextFuncPtr (*RGFW_glXGetProcAddressARBProc)(const u8*);
+ typedef PFNGLXCHOOSEFBCONFIGPROC RGFW_glXChooseFBConfigProc;
+ typedef void (*RGFW_glXDestroyContextProc)(Display *dpy, GLXContext ctx);
+ typedef GLXWindow (*RGFW_glXCreateWindowProc)(Display*,GLXFBConfig,Window,const int*);
+ typedef void (*RGFW_glXDestroyWindowProc)(Display*,GLXWindow);
+ typedef int (*RGFW_GLX_MESA_swap_controlProc) (int);
+ typedef int (*RGFW_GLX_SGI_swap_controlProc) (int);
+
+ RGFW_glXCreateContextAttribsARBProc RGFW_glXCreateContextAttribsARB;
+ RGFW_glXQueryExtensionsStringProc RGFW_glXQueryExtensionsString;
+ RGFW_glXChooseVisualProc RGFW_glXChooseVisual;
+ RGFW_glXCreateContextProc RGFW_glXCreateContext;
+ RGFW_glXMakeCurrentProc RGFW_glXMakeCurrent;
+ RGFW_glXGetCurrentContextProc RGFW_glXGetCurrentContext;
+ RGFW_glXGetCurrentDrawableProc RGFW_glXGetCurrentDrawable;
+ RGFW_glXSwapBuffersProc RGFW_glXSwapBuffers;
+ RGFW_glXSwapIntervalEXTProc RGFW_glXSwapIntervalEXT;
+ RGFW_glXGetVisualFromFBConfigProc RGFW_glXGetVisualFromFBConfig;
+ RGFW_glXGetFBConfigAttribProc RGFW_glXGetFBConfigAttrib;
+ RGFW_glXGetProcAddressARBProc RGFW_glXGetProcAddressARB;
+ RGFW_glXChooseFBConfigProc RGFW_glXChooseFBConfig;
+ RGFW_glXDestroyContextProc RGFW_glXDestroyContext;
+ RGFW_glXCreateWindowProc RGFW_glXCreateWindow;
+ RGFW_glXDestroyWindowProc RGFW_glXDestroyWindow;
+ RGFW_GLX_MESA_swap_controlProc RGFW_GLX_MESA_swap_control;
+ RGFW_GLX_SGI_swap_controlProc RGFW_GLX_SGI_swap_control;
+
+ RGFW_bool RGFW_loadGL(void) {
+ RGFW_ASSERT(_RGFW && "An RGFW context must be initialized using RGFW_init and/or set with RGFW_setInfo");
+ if (RGFW_usingWayland()) return RGFW_FALSE;
+ if (_RGFW->nativeGL_handle && _RGFW->glGetProcAddress != NULL) {
+ return RGFW_TRUE;
+ }
+
+ const char* glxSonames[] = {
+ #if defined(__CYGWIN__)
+ "libGL-1.so",
+ #elif defined(__OpenBSD__) || defined(__NetBSD__)
+ "libGL.so",
+ #else
+ "libGLX.so.0",
+ "libGL.so.1",
+ "libGL.so",
+ #endif
+ };
+
+ for (int i = 0; sizeof(glxSonames) / sizeof(char*); i++) {
+ _RGFW->nativeGL_handle = dlopen(glxSonames[i], RTLD_LAZY | RTLD_LOCAL);
+ if (_RGFW->nativeGL_handle)
+ break;
+ }
+
+ void* ptr = dlsym(_RGFW->nativeGL_handle, "glXGetProcAddress");
+ RGFW_ASSERT(ptr != NULL);
+ RGFW_MEMCPY(&_RGFW->glGetProcAddress, &ptr, sizeof(void*));
+ #define RGFW_PROC_DEF(name) if (RGFW_##name == NULL) RGFW_##name = (RGFW_##name##Proc)_RGFW->glGetProcAddress(#name);
+
+ RGFW_PROC_DEF(glXChooseVisual);
+ RGFW_PROC_DEF(glXCreateContext);
+ RGFW_PROC_DEF(glXMakeCurrent);
+ RGFW_PROC_DEF(glXGetCurrentContext);
+ RGFW_PROC_DEF(glXGetCurrentDrawable);
+ RGFW_PROC_DEF(glXSwapBuffers);
+ RGFW_PROC_DEF(glXGetVisualFromFBConfig);
+ RGFW_PROC_DEF(glXGetFBConfigAttrib);
+ RGFW_PROC_DEF(glXGetProcAddressARB);
+ RGFW_PROC_DEF(glXChooseFBConfig);
+ RGFW_PROC_DEF(glXDestroyContext);
+ RGFW_PROC_DEF(glXCreateWindow);
+ RGFW_PROC_DEF(glXDestroyWindow);
+ RGFW_PROC_DEF(glXQueryExtensionsString);
+ RGFW_PROC_DEF(glXCreateContextAttribsARB);
+ RGFW_PROC_DEF(glXGetProcAddressARB);
+ RGFW_PROC_DEF(GLX_SGI_swap_control);
+ RGFW_PROC_DEF(GLX_MESA_swap_control);
+ RGFW_PROC_DEF(glXSwapIntervalEXT);
+
+ if (RGFW_glXSwapIntervalEXT == NULL) {
+ if (RGFW_GLX_MESA_swap_control == NULL && RGFW_GLX_SGI_swap_control == NULL) {
+ RGFW_debugCallback(RGFW_typeWarning, RGFW_infoOpenGL, "Failed to load swap interval function");
+ } else {
+ RGFW_debugCallback(RGFW_typeWarning, RGFW_infoOpenGL, "Failed to load swap interval function, fallingback to the native swapinterval function");
+ }
+ }
+ #undef RGFW_PROC_DEF
+
+ return RGFW_TRUE;
+ }
#endif
/* atoms needed for drag and drop */
@@ -6304,31 +7145,32 @@ void RGFW_FUNC(RGFW_surface_freePtr) (RGFW_surface* surface) {
return;
}
-#define RGFW_LOAD_ATOM(name) \
- static Atom name = 0; \
- if (name == 0) name = XInternAtom(_RGFW->display, #name, False);
-
void RGFW_FUNC(RGFW_window_setBorder) (RGFW_window* win, RGFW_bool border) {
RGFW_setBit(&win->internal.flags, RGFW_windowNoBorder, !border);
- RGFW_LOAD_ATOM(_MOTIF_WM_HINTS);
struct __x11WindowHints {
- unsigned long flags, functions, decorations, status;
+ unsigned long flags, functions, decorations;
long input_mode;
+ unsigned long status;
} hints;
+ RGFW_MEMZERO(&hints, sizeof(hints));
hints.flags = 2;
- hints.decorations = border;
-
- XChangeProperty(_RGFW->display, win->src.window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropModeReplace, (u8*)&hints, 5);
-
- if (RGFW_window_isHidden(win) == 0) {
- RGFW_window_hide(win);
- RGFW_window_show(win);
- }
+ hints.decorations = border ? 1 : 0;
+ XChangeProperty(_RGFW->display, win->src.window, _RGFW->_MOTIF_WM_HINTS, _RGFW->_MOTIF_WM_HINTS, 32, PropModeReplace, (u8*)&hints, (sizeof(hints) / sizeof(long)));
}
void RGFW_FUNC(RGFW_window_setRawMouseModePlatform) (RGFW_window* win, RGFW_bool state) {
- RGFW_UNUSED(win); RGFW_UNUSED(state);
+ RGFW_UNUSED(win);
+ unsigned char mask[XIMaskLen(XI_RawMotion)];
+ RGFW_MEMZERO(mask, sizeof(mask));
+ if (state) XISetMask(mask, XI_RawMotion);
+
+ XIEventMask em;
+ em.deviceid = XIAllMasterDevices;
+ em.mask_len = sizeof(mask);
+ em.mask = mask;
+
+ XISelectEvents(_RGFW->display, XDefaultRootWindow(_RGFW->display), &em, 1);
}
void RGFW_FUNC(RGFW_window_captureMousePlatform) (RGFW_window* win, RGFW_bool state) {
@@ -6369,10 +7211,29 @@ int RGFW_XErrorHandler(Display* display, XErrorEvent* ev) {
RGFW_debugCallback(RGFW_typeError, RGFW_errX11, buf);
_RGFW->x11Error = ev;
+
+ #ifdef RGFW_X11_CRASH_ON_ERROR
+ RGFW_ASSERT(0);
+ #endif
+
return 0;
}
-void RGFW_XCreateWindow (XVisualInfo visual, const char* name, RGFW_windowFlags flags, RGFW_window* win) {
+char* RGFW_XGetWindowName(Window window) {
+ Atom actualType;
+ int actualFormat;
+ unsigned long nitems, bytesAfter;
+ char* name = NULL;
+
+ if (XGetWindowProperty(_RGFW->display, window, _RGFW->_NET_WM_NAME, 0, (~0L), False, _RGFW->UTF8_STRING, &actualType, &actualFormat, &nitems, &bytesAfter, (u8**)&name) == Success && name) {
+ return name;
+ }
+
+ if (XFetchName(_RGFW->display, window, &name) != Success) return NULL;
+ return name;
+}
+
+RGFW_bool RGFW_XCreateWindow (XVisualInfo visual, const char* name, RGFW_windowFlags flags, RGFW_window* win) {
i64 event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask |
LeaveWindowMask | EnterWindowMask | ExposureMask | VisibilityChangeMask | PropertyChangeMask;
@@ -6394,6 +7255,8 @@ void RGFW_XCreateWindow (XVisualInfo visual, const char* name, RGFW_windowFlags
0, visual.depth, InputOutput, visual.visual,
CWBorderPixel | CWColormap | CWEventMask, &swa);
+ if (win->src.window == 0) return RGFW_FALSE;
+
win->src.flashEnd = 0;
XFreeColors(_RGFW->display, cmap, NULL, 0, 0);
@@ -6410,22 +7273,17 @@ void RGFW_XCreateWindow (XVisualInfo visual, const char* name, RGFW_windowFlags
win->src.ic = XCreateIC(_RGFW->im, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, win->src.window, XNFocusWindow, win->src.window, XNDestroyCallback, &callback, NULL);
}
-
/* In your .desktop app, if you set the property
StartupWMClass=RGFW that will assoicate the launcher icon
with your application - robrohan */
- if (_RGFW->className == NULL)
- _RGFW->className = (char*)name;
XClassHint hint;
+ hint.res_name = (char*)(name ? name : "RGFW");
hint.res_class = (char*)_RGFW->className;
-
- if (_RGFW->instName == NULL) hint.res_name = (char*)name;
- else hint.res_name = (char*)_RGFW->instName;
-
XSetClassHint(_RGFW->display, win->src.window, &hint);
XWMHints hints;
+ RGFW_MEMZERO(&hints, sizeof(hints));
hints.flags = StateHint;
hints.initial_state = NormalState;
@@ -6434,8 +7292,7 @@ void RGFW_XCreateWindow (XVisualInfo visual, const char* name, RGFW_windowFlags
XSelectInput(_RGFW->display, (Drawable) win->src.window, event_mask); /*!< tell X11 what events we want */
/* make it so the user can't close the window until the program does */
- RGFW_LOAD_ATOM(WM_DELETE_WINDOW);
- XSetWMProtocols(_RGFW->display, (Drawable) win->src.window, &WM_DELETE_WINDOW, 1);
+ XSetWMProtocols(_RGFW->display, (Drawable) win->src.window, &_RGFW->WM_DELETE_WINDOW, 1);
/* set the background */
RGFW_window_setName(win, name);
@@ -6445,26 +7302,22 @@ void RGFW_XCreateWindow (XVisualInfo visual, const char* name, RGFW_windowFlags
win->internal.flags |= RGFW_windowAllowDND;
/* actions */
- Atom XdndAware = XInternAtom(_RGFW->display, "XdndAware", False);
const u8 version = 5;
XChangeProperty(_RGFW->display, win->src.window,
- XdndAware, 4, 32,
+ _RGFW->XdndAware, 4, 32,
PropModeReplace, &version, 1); /*!< turns on drag and drop */
}
#ifdef RGFW_ADVANCED_SMOOTH_RESIZE
- RGFW_LOAD_ATOM(_NET_WM_SYNC_REQUEST_COUNTER)
- RGFW_LOAD_ATOM(_NET_WM_SYNC_REQUEST)
-
- Atom protcols[2] = {_NET_WM_SYNC_REQUEST, WM_DELETE_WINDOW};
+ Atom protcols[2] = {_RGFW->_NET_WM_SYNC_REQUEST, _RGFW->WM_DELETE_WINDOW};
XSetWMProtocols(_RGFW->display, win->src.window, protcols, 2);
XSyncValue initial_value;
XSyncIntToValue(&initial_value, 0);
win->src.counter = XSyncCreateCounter(_RGFW->display, initial_value);
- XChangeProperty(_RGFW->display, win->src.window, _NET_WM_SYNC_REQUEST_COUNTER, XA_CARDINAL, 32, PropModeReplace, (u8*)&win->src.counter, 1);
+ XChangeProperty(_RGFW->display, win->src.window, _RGFW->_NET_WM_SYNC_REQUEST_COUNTER, XA_CARDINAL, 32, PropModeReplace, (u8*)&win->src.counter, 1);
#endif
win->src.x = win->x;
@@ -6477,6 +7330,8 @@ void RGFW_XCreateWindow (XVisualInfo visual, const char* name, RGFW_windowFlags
/* stupid hack to make resizing the window less bad */
XSetWindowBackgroundPixmap(_RGFW->display, win->src.window, None);
+
+ return RGFW_TRUE;
}
RGFW_window* RGFW_FUNC(RGFW_createWindowPlatform) (const char* name, RGFW_windowFlags flags, RGFW_window* win) {
@@ -6487,12 +7342,12 @@ RGFW_window* RGFW_FUNC(RGFW_createWindowPlatform) (const char* name, RGFW_window
XVisualInfo visual;
RGFW_window_getVisual(&visual, RGFW_BOOL(win->internal.flags & RGFW_windowTransparent));
- RGFW_XCreateWindow(visual, name, flags, win);
+ if (RGFW_XCreateWindow(visual, name, flags, win) == RGFW_FALSE) return NULL;
return win; /*return newly created window */
}
RGFW_bool RGFW_FUNC(RGFW_getGlobalMouse) (i32* fX, i32* fY) {
- RGFW_init();
+ RGFW_ASSERT(_RGFW && "An RGFW context must be initialized using RGFW_init and/or set with RGFW_setInfo");
i32 x, y;
u32 z;
Window window1, window2;
@@ -6502,28 +7357,22 @@ RGFW_bool RGFW_FUNC(RGFW_getGlobalMouse) (i32* fX, i32* fY) {
RGFWDEF void RGFW_XHandleClipboardSelection(XEvent* event);
void RGFW_XHandleClipboardSelection(XEvent* event) { RGFW_UNUSED(event);
- RGFW_LOAD_ATOM(ATOM_PAIR);
- RGFW_LOAD_ATOM(MULTIPLE);
- RGFW_LOAD_ATOM(TARGETS);
- RGFW_LOAD_ATOM(SAVE_TARGETS);
- RGFW_LOAD_ATOM(UTF8_STRING);
-
const XSelectionRequestEvent* request = &event->xselectionrequest;
Atom formats[2] = {0};
- formats[0] = UTF8_STRING;
+ formats[0] = _RGFW->UTF8_STRING;
formats[1] = XA_STRING;
const int formatCount = sizeof(formats) / sizeof(formats[0]);
- if (request->target == TARGETS) {
+ if (request->target == _RGFW->TARGETS) {
Atom targets[4] = {0};
- targets[0] = TARGETS;
- targets[1] = MULTIPLE;
- targets[2] = UTF8_STRING;
+ targets[0] = _RGFW->TARGETS;
+ targets[1] = _RGFW->MULTIPLE;
+ targets[2] = _RGFW->UTF8_STRING;
targets[3] = XA_STRING;
XChangeProperty(_RGFW->display, request->requestor, request->property,
XA_ATOM, 32, PropModeReplace, (u8*) targets, sizeof(targets) / sizeof(Atom));
- } else if (request->target == MULTIPLE) {
+ } else if (request->target == _RGFW->MULTIPLE) {
Atom* targets = NULL;
Atom actualType = 0;
@@ -6531,24 +7380,24 @@ void RGFW_XHandleClipboardSelection(XEvent* event) { RGFW_UNUSED(event);
unsigned long count = 0, bytesAfter = 0;
XGetWindowProperty(_RGFW->display, request->requestor, request->property, 0, LONG_MAX,
- False, ATOM_PAIR, &actualType, &actualFormat, &count, &bytesAfter, (u8**) &targets);
+ False, _RGFW->ATOM_PAIR, &actualType, &actualFormat, &count, &bytesAfter, (u8**) &targets);
unsigned long i;
for (i = 0; i < (u32)count; i += 2) {
- if (targets[i] == UTF8_STRING || targets[i] == XA_STRING)
+ if (targets[i] == _RGFW->UTF8_STRING || targets[i] == XA_STRING)
XChangeProperty(_RGFW->display, request->requestor, targets[i + 1], targets[i],
- 8, PropModeReplace, (const unsigned char *)_RGFW->clipboard, (i32)_RGFW->clipboard_len);
+ 8, PropModeReplace, (const unsigned char *)_RGFW->unixClipboard->data, (i32)_RGFW->unixClipboard->length);
else
targets[i + 1] = None;
}
XChangeProperty(_RGFW->display,
- request->requestor, request->property, ATOM_PAIR, 32,
+ request->requestor, request->property, _RGFW->ATOM_PAIR, 32,
PropModeReplace, (u8*) targets, (i32)count);
XFlush(_RGFW->display);
XFree(targets);
- } else if (request->target == SAVE_TARGETS)
+ } else if (request->target == _RGFW->SAVE_TARGETS)
XChangeProperty(_RGFW->display, request->requestor, request->property, 0, 32, PropModeReplace, NULL, 0);
else {
int i;
@@ -6556,7 +7405,7 @@ void RGFW_XHandleClipboardSelection(XEvent* event) { RGFW_UNUSED(event);
if (request->target != formats[i])
continue;
XChangeProperty(_RGFW->display, request->requestor, request->property, request->target,
- 8, PropModeReplace, (u8*) _RGFW->clipboard, (i32)_RGFW->clipboard_len);
+ 8, PropModeReplace, (u8*) _RGFW->unixClipboard->data, (i32)_RGFW->unixClipboard->length);
}
}
@@ -6583,6 +7432,11 @@ RGFW_key RGFW_FUNC(RGFW_physicalToMappedKey) (RGFW_key key) {
}
switch (sym) {
+ case XK_BackSpace: return RGFW_keyBackSpace;
+ case XK_Tab: return RGFW_keyTab;
+ case XK_Return: return RGFW_keyReturn;
+ case XK_Escape: return RGFW_keyEscape;
+ case XK_Delete: return RGFW_keyDelete;
case XK_F1: return RGFW_keyF1;
case XK_F2: return RGFW_keyF2;
case XK_F3: return RGFW_keyF3;
@@ -6656,24 +7510,11 @@ RGFW_key RGFW_FUNC(RGFW_physicalToMappedKey) (RGFW_key key) {
RGFWDEF void RGFW_XHandleEvent(void);
void RGFW_XHandleEvent(void) {
- RGFW_LOAD_ATOM(XdndTypeList);
- RGFW_LOAD_ATOM(XdndSelection);
- RGFW_LOAD_ATOM(XdndEnter);
- RGFW_LOAD_ATOM(XdndPosition);
- RGFW_LOAD_ATOM(XdndStatus);
- RGFW_LOAD_ATOM(XdndLeave);
- RGFW_LOAD_ATOM(XdndDrop);
- RGFW_LOAD_ATOM(XdndFinished);
- RGFW_LOAD_ATOM(XdndActionCopy);
- RGFW_LOAD_ATOM(_NET_WM_SYNC_REQUEST);
- RGFW_LOAD_ATOM(WM_PROTOCOLS);
- RGFW_LOAD_ATOM(WM_STATE);
- RGFW_LOAD_ATOM(_NET_WM_STATE);
-
static float deltaX = 0.0f;
static float deltaY = 0.0f;
XEvent E;
+ RGFW_MEMZERO(&E, sizeof(E));
XNextEvent(_RGFW->display, &E);
@@ -6682,12 +7523,10 @@ void RGFW_XHandleEvent(void) {
deltaY = 0.0f;
}
-#ifndef RGFW_NO_XRANDR
if (E.type == _RGFW->xrandrEventBase + RRNotify) {
RGFW_pollMonitors();
return;
}
-#endif
switch (E.type) {
case SelectionRequest:
@@ -6730,7 +7569,7 @@ void RGFW_XHandleEvent(void) {
}
if (win->src.flashEnd) {
- if ((win->src.flashEnd <= RGFW_linux_getTimeNS()) || RGFW_window_isInFocus(win)) {
+ if ((win->src.flashEnd <= RGFW_unix_getTimeNS()) || RGFW_window_isInFocus(win)) {
RGFW_window_flash(win, RGFW_flashCancel);
}
}
@@ -6862,11 +7701,11 @@ void RGFW_XHandleEvent(void) {
break;
}
case MotionNotify:
- RGFW_mousePosCallback(win, E.xmotion.x, E.xmotion.y);
+ RGFW_mouseMotionCallback(win, E.xmotion.x, E.xmotion.y);
break;
case Expose: {
- RGFW_windowRefreshCallback(win, 0, 0, win->w, win->h);
+ RGFW_windowRefreshCallback(win, E.xexpose.x, E.xexpose.y, E.xexpose.width, E.xexpose.height);
#ifdef RGFW_ADVANCED_SMOOTH_RESIZE
XSyncValue value;
@@ -6879,12 +7718,12 @@ void RGFW_XHandleEvent(void) {
case PropertyNotify:
if (E.xproperty.state != PropertyNewValue) break;
- if (E.xproperty.atom == WM_STATE) {
+ if (E.xproperty.atom == _RGFW->WM_STATE) {
if (RGFW_window_isMinimized(win) && !(win->internal.flags & RGFW_windowMinimized)) {
RGFW_windowMinimizedCallback(win);
break;
}
- } else if (E.xproperty.atom == _NET_WM_STATE) {
+ } else if (E.xproperty.atom == _RGFW->_NET_WM_STATE) {
if (RGFW_window_isMaximized(win) && !(win->internal.flags & RGFW_windowMaximize)) {
RGFW_windowMaximizedCallback(win, win->x, win->y, win->w, win->h);
break;
@@ -6895,14 +7734,13 @@ void RGFW_XHandleEvent(void) {
break;
case MapNotify: case UnmapNotify: RGFW_window_checkMode(win); break;
case ClientMessage: {
- RGFW_LOAD_ATOM(WM_DELETE_WINDOW);
/* if the client closed the window */
- if (E.xclient.data.l[0] == (long)WM_DELETE_WINDOW) {
+ if (E.xclient.data.l[0] == (long)_RGFW->WM_DELETE_WINDOW) {
RGFW_windowCloseCallback(win);
break;
}
#ifdef RGFW_ADVANCED_SMOOTH_RESIZE
- if (E.xclient.message_type == WM_PROTOCOLS && (Atom)E.xclient.data.l[0] == _NET_WM_SYNC_REQUEST) {
+ if (E.xclient.message_type == _RGFW->WM_PROTOCOLS && (Atom)E.xclient.data.l[0] == _RGFW->_NET_WM_SYNC_REQUEST) {
RGFW_windowRefreshCallback(win, 0, 0, win->w, win->h);
win->src.counter_value = 0;
win->src.counter_value |= E.xclient.data.l[2];
@@ -6921,7 +7759,7 @@ void RGFW_XHandleEvent(void) {
i32 dragX = 0;
i32 dragY = 0;
- if (E.xclient.message_type == XdndEnter) {
+ if (E.xclient.message_type == _RGFW->XdndEnter) {
unsigned long count;
Atom* formats;
Atom real_formats[3];
@@ -6936,7 +7774,7 @@ void RGFW_XHandleEvent(void) {
unsigned long bytesAfter;
XGetWindowProperty(
- _RGFW->display, _RGFW->x11Source, XdndTypeList,
+ _RGFW->display, _RGFW->x11Source, _RGFW->XdndTypeList,
0, LONG_MAX, False, 4,
&actualType, &actualFormat, &count, &bytesAfter, (u8**)&formats
);
@@ -6954,13 +7792,10 @@ void RGFW_XHandleEvent(void) {
formats = real_formats;
}
- Atom XtextPlain = XInternAtom(_RGFW->display, "text/plain", False);
- Atom XtextUriList = XInternAtom(_RGFW->display, "text/uri-list", False);
-
size_t i;
for (i = 0; i < count; i++) {
- if (formats[i] == XtextUriList) _RGFW->x11TransferType = RGFW_dataFile;
- else if (formats[i] == XtextPlain) _RGFW->x11TransferType = RGFW_dataText;
+ if (formats[i] == _RGFW->XtextUriList) _RGFW->x11TransferType = RGFW_dataFile;
+ else if (formats[i] == _RGFW->XtextPlain) _RGFW->x11TransferType = RGFW_dataText;
else continue;
_RGFW->x11Format = (int)formats[i];
@@ -6973,7 +7808,7 @@ void RGFW_XHandleEvent(void) {
RGFW_dataDragCallback(win, _RGFW->x11TransferType , RGFW_dndActionEnter, dragX, dragY);
- } else if (E.xclient.message_type == XdndPosition) {
+ } else if (E.xclient.message_type == _RGFW->XdndPosition) {
const i32 xabs = (E.xclient.data.l[2] >> 16) & 0xffff;
const i32 yabs = (E.xclient.data.l[2]) & 0xffff;
Window dummy;
@@ -6987,10 +7822,10 @@ void RGFW_XHandleEvent(void) {
dragX = xpos;
dragY = ypos;
- RGFW_mousePosCallback(win, xpos, ypos);
+ RGFW_mouseMotionCallback(win, xpos, ypos);
XEvent reply = { ClientMessage };
reply.xclient.window = _RGFW->x11Source;
- reply.xclient.message_type = XdndStatus;
+ reply.xclient.message_type = _RGFW->XdndStatus;
reply.xclient.format = 32;
reply.xclient.data.l[0] = (long)win->src.window;
reply.xclient.data.l[2] = 0;
@@ -6999,7 +7834,7 @@ void RGFW_XHandleEvent(void) {
if (_RGFW->x11Format) {
reply.xclient.data.l[1] = 1;
if (_RGFW->x11Version >= 2)
- reply.xclient.data.l[4] = (long)XdndActionCopy;
+ reply.xclient.data.l[4] = (long)_RGFW->XdndActionCopy;
}
XSendEvent(_RGFW->display, _RGFW->x11Source, False, NoEventMask, &reply);
@@ -7007,21 +7842,21 @@ void RGFW_XHandleEvent(void) {
RGFW_dataDragCallback(win, _RGFW->x11TransferType, RGFW_dndActionMove, dragX, dragY);
- } else if (E.xclient.message_type == XdndLeave) {
+ } else if (E.xclient.message_type == _RGFW->XdndLeave) {
RGFW_dataDragCallback(win, _RGFW->x11TransferType, RGFW_dndActionExit, dragX, dragY);
- } else if (E.xclient.message_type == XdndDrop) {
+ } else if (E.xclient.message_type == _RGFW->XdndDrop) {
if (_RGFW->x11Format) {
Time time = (_RGFW->x11Version >= 1)
? (Time)E.xclient.data.l[2]
: CurrentTime;
XConvertSelection(
- _RGFW->display, XdndSelection, (Atom)_RGFW->x11Format,
- XdndSelection, win->src.window, time
+ _RGFW->display, _RGFW->XdndSelection, (Atom)_RGFW->x11Format,
+ _RGFW->XdndSelection, win->src.window, time
);
} else if (_RGFW->x11Version >= 2) {
XEvent reply = { ClientMessage };
reply.xclient.window = _RGFW->x11Source;
- reply.xclient.message_type = XdndFinished;
+ reply.xclient.message_type = _RGFW->XdndFinished;
reply.xclient.format = 32;
reply.xclient.data.l[0] = (long)win->src.window;
reply.xclient.data.l[1] = 0;
@@ -7034,7 +7869,7 @@ void RGFW_XHandleEvent(void) {
} break;
case SelectionNotify: {
/* this is only for checking for xdnd drops */
- if (!(win->internal.enabledEvents & RGFW_dataDropFlag) || E.xselection.property != XdndSelection || !(win->internal.flags & RGFW_windowAllowDND))
+ if (!(win->internal.enabledEvents & RGFW_dataDropFlag) || E.xselection.property != _RGFW->XdndSelection || !(win->internal.flags & RGFW_windowAllowDND))
return;
char* data;
unsigned long result;
@@ -7055,11 +7890,11 @@ void RGFW_XHandleEvent(void) {
if (_RGFW->x11Version >= 2) {
XEvent reply = { ClientMessage };
reply.xclient.window = _RGFW->x11Source;
- reply.xclient.message_type = XdndFinished;
+ reply.xclient.message_type = _RGFW->XdndFinished;
reply.xclient.format = 32;
reply.xclient.data.l[0] = (long)win->src.window;
reply.xclient.data.l[1] = (long int)result;
- reply.xclient.data.l[2] = (long int)XdndActionCopy;
+ reply.xclient.data.l[2] = (long int)_RGFW->XdndActionCopy;
XSendEvent(_RGFW->display, _RGFW->x11Source, False, NoEventMask, &reply);
XFlush(_RGFW->display);
}
@@ -7108,10 +7943,10 @@ void RGFW_XHandleEvent(void) {
}
/* detect move */
- if (E.xconfigure.x != win->src.x || E.xconfigure.y != win->src.y) {
- win->src.x = E.xconfigure.x;
- win->src.y = E.xconfigure.y;
- RGFW_windowMovedCallback(win, E.xconfigure.x, E.xconfigure.y);
+ if (x != win->src.x || y != win->src.y) {
+ win->src.x = x;
+ win->src.y = y;
+ RGFW_windowMovedCallback(win, x, y);
}
return;
}
@@ -7142,21 +7977,12 @@ void RGFW_FUNC(RGFW_pollEvents) (void) {
}
}
-void RGFW_FUNC(RGFW_window_move) (RGFW_window* win, i32 x, i32 y) {
- RGFW_ASSERT(win != NULL);
- win->x = x;
- win->y = y;
-
+void RGFW_FUNC(RGFW_window_movePlatform) (RGFW_window* win, i32 x, i32 y) {
XMoveWindow(_RGFW->display, win->src.window, x, y);
- return;
}
-void RGFW_FUNC(RGFW_window_resize) (RGFW_window* win, i32 w, i32 h) {
- RGFW_ASSERT(win != NULL);
- win->w = (i32)w;
- win->h = (i32)h;
-
+void RGFW_FUNC(RGFW_window_resizePlatform) (RGFW_window* win, i32 w, i32 h) {
XResizeWindow(_RGFW->display, win->src.window, (u32)w, (u32)h);
if ((win->internal.flags & RGFW_windowNoResize)) {
@@ -7229,32 +8055,23 @@ void RGFW_FUNC(RGFW_window_setMaxSize) (RGFW_window* win, i32 w, i32 h) {
void RGFW_toggleXMaximized(RGFW_window* win, RGFW_bool maximized);
void RGFW_toggleXMaximized(RGFW_window* win, RGFW_bool maximized) {
RGFW_ASSERT(win != NULL);
- RGFW_LOAD_ATOM(_NET_WM_STATE);
- RGFW_LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
- RGFW_LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
XEvent xev = {0};
xev.type = ClientMessage;
xev.xclient.window = win->src.window;
- xev.xclient.message_type = _NET_WM_STATE;
+ xev.xclient.message_type = _RGFW->_NET_WM_STATE;
xev.xclient.format = 32;
xev.xclient.data.l[0] = maximized;
- xev.xclient.data.l[1] = (long int)_NET_WM_STATE_MAXIMIZED_HORZ;
- xev.xclient.data.l[2] = (long int)_NET_WM_STATE_MAXIMIZED_VERT;
+ xev.xclient.data.l[1] = (long int)_RGFW->_NET_WM_STATE_MAXIMIZED_HORZ;
+ xev.xclient.data.l[2] = (long int)_RGFW->_NET_WM_STATE_MAXIMIZED_VERT;
xev.xclient.data.l[3] = 0;
xev.xclient.data.l[4] = 0;
XSendEvent(_RGFW->display, DefaultRootWindow(_RGFW->display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
}
-void RGFW_FUNC(RGFW_window_maximize) (RGFW_window* win) {
- win->internal.oldX = win->x;
- win->internal.oldY = win->y;
- win->internal.oldW = win->w;
- win->internal.oldH = win->h;
-
+void RGFW_FUNC(RGFW_window_maximizePlatform) (RGFW_window* win) {
RGFW_toggleXMaximized(win, 1);
- RGFW_window_fetchSize(win, NULL, NULL);
return;
}
@@ -7272,19 +8089,18 @@ void RGFW_FUNC(RGFW_window_focus) (RGFW_window* win) {
void RGFW_FUNC(RGFW_window_raise) (RGFW_window* win) {
RGFW_ASSERT(win);
XMapRaised(_RGFW->display, win->src.window);
- RGFW_window_setFullscreen(win, RGFW_window_isFullscreen(win));
+ RGFW_window_setFullscreenPlatform(win, RGFW_window_isFullscreen(win));
}
void RGFW_window_setXAtom(RGFW_window* win, Atom netAtom, RGFW_bool fullscreen);
void RGFW_window_setXAtom(RGFW_window* win, Atom netAtom, RGFW_bool fullscreen) {
RGFW_ASSERT(win != NULL);
- RGFW_LOAD_ATOM(_NET_WM_STATE);
XEvent xev = {0};
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
- xev.xclient.message_type = _NET_WM_STATE;
+ xev.xclient.message_type = _RGFW->_NET_WM_STATE;
xev.xclient.window = win->src.window;
xev.xclient.format = 32;
xev.xclient.data.l[0] = fullscreen;
@@ -7294,48 +8110,33 @@ void RGFW_window_setXAtom(RGFW_window* win, Atom netAtom, RGFW_bool fullscreen)
XSendEvent(_RGFW->display, DefaultRootWindow(_RGFW->display), False, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
}
-void RGFW_FUNC(RGFW_window_setFullscreen)(RGFW_window* win, RGFW_bool fullscreen) {
- RGFW_ASSERT(win != NULL);
-
- if (fullscreen) {
- win->internal.flags |= RGFW_windowFullscreen;
- win->internal.oldX = win->x;
- win->internal.oldY = win->y;
- win->internal.oldW = win->w;
- win->internal.oldH = win->h;
- }
- else win->internal.flags &= ~(u32)RGFW_windowFullscreen;
-
+void RGFW_FUNC(RGFW_window_setFullscreenPlatform)(RGFW_window* win, RGFW_bool fullscreen) {
XRaiseWindow(_RGFW->display, win->src.window);
- RGFW_LOAD_ATOM(_NET_WM_STATE_FULLSCREEN);
- RGFW_window_setXAtom(win, _NET_WM_STATE_FULLSCREEN, fullscreen);
+ RGFW_window_setXAtom(win, _RGFW->_NET_WM_STATE_FULLSCREEN, fullscreen);
if (!(win->internal.flags & RGFW_windowTransparent)) {
const unsigned char value = fullscreen;
- RGFW_LOAD_ATOM(_NET_WM_BYPASS_COMPOSITOR);
XChangeProperty(
_RGFW->display, win->src.window,
- _NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
+ _RGFW->_NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
PropModeReplace, &value, 1);
}
}
void RGFW_FUNC(RGFW_window_setFloating)(RGFW_window* win, RGFW_bool floating) {
RGFW_ASSERT(win != NULL);
- RGFW_LOAD_ATOM(_NET_WM_STATE_ABOVE);
- RGFW_window_setXAtom(win, _NET_WM_STATE_ABOVE, floating);
+ RGFW_window_setXAtom(win, _RGFW->_NET_WM_STATE_ABOVE, floating);
}
void RGFW_FUNC(RGFW_window_setOpacity)(RGFW_window* win, u8 opacity) {
RGFW_ASSERT(win != NULL);
const u32 value = (u32) (0xffffffffu * (double) opacity);
- RGFW_LOAD_ATOM(NET_WM_WINDOW_OPACITY);
XChangeProperty(_RGFW->display, win->src.window,
- NET_WM_WINDOW_OPACITY, XA_CARDINAL, 32, PropModeReplace, (unsigned char*) &value, 1);
+ _RGFW->NET_WM_WINDOW_OPACITY, XA_CARDINAL, 32, PropModeReplace, (unsigned char*) &value, 1);
}
-void RGFW_FUNC(RGFW_window_minimize)(RGFW_window* win) {
+void RGFW_FUNC(RGFW_window_minimizePlatform)(RGFW_window* win) {
RGFW_ASSERT(win != NULL);
if (RGFW_window_isMaximized(win)) return;
@@ -7348,26 +8149,19 @@ void RGFW_FUNC(RGFW_window_minimize)(RGFW_window* win) {
XFlush(_RGFW->display);
}
-void RGFW_FUNC(RGFW_window_restore)(RGFW_window* win) {
+void RGFW_FUNC(RGFW_window_restorePlatform)(RGFW_window* win) {
RGFW_ASSERT(win != NULL);
RGFW_toggleXMaximized(win, RGFW_FALSE);
- RGFW_window_move(win, win->internal.oldX, win->internal.oldY);
- RGFW_window_resize(win, win->internal.oldW, win->internal.oldH);
-
- RGFW_window_show(win);
- XFlush(_RGFW->display);
+ XFlush(_RGFW->display);
}
RGFW_bool RGFW_FUNC(RGFW_window_isFloating)(RGFW_window* win) {
- RGFW_LOAD_ATOM(_NET_WM_STATE);
- RGFW_LOAD_ATOM(_NET_WM_STATE_ABOVE);
-
Atom actual_type;
int actual_format;
unsigned long nitems, bytes_after;
Atom* prop_return = NULL;
- int status = XGetWindowProperty(_RGFW->display, win->src.window, _NET_WM_STATE, 0, (~0L), False, XA_ATOM,
+ int status = XGetWindowProperty(_RGFW->display, win->src.window, _RGFW->_NET_WM_STATE, 0, (~0L), False, XA_ATOM,
&actual_type, &actual_format, &nitems, &bytes_after,
(unsigned char **)&prop_return);
@@ -7376,7 +8170,7 @@ RGFW_bool RGFW_FUNC(RGFW_window_isFloating)(RGFW_window* win) {
unsigned long i;
for (i = 0; i < nitems; i++)
- if (prop_return[i] == _NET_WM_STATE_ABOVE) return RGFW_TRUE;
+ if (prop_return[i] == _RGFW->_NET_WM_STATE_ABOVE) return RGFW_TRUE;
if (prop_return)
XFree(prop_return);
@@ -7390,10 +8184,8 @@ void RGFW_FUNC(RGFW_window_setName)(RGFW_window* win, const char* name) {
Xutf8SetWMProperties(_RGFW->display, win->src.window, name, name, NULL, 0, NULL, NULL, NULL);
XStoreName(_RGFW->display, win->src.window, name);
- RGFW_LOAD_ATOM(_NET_WM_NAME); RGFW_LOAD_ATOM(UTF8_STRING);
-
XChangeProperty(
- _RGFW->display, win->src.window, _NET_WM_NAME, UTF8_STRING,
+ _RGFW->display, win->src.window, _RGFW->_NET_WM_NAME, _RGFW->UTF8_STRING,
8, PropModeReplace, (u8*)name, (int)RGFW_unix_stringlen(name)
);
}
@@ -7414,11 +8206,10 @@ void RGFW_FUNC(RGFW_window_setMousePassthrough) (RGFW_window* win, RGFW_bool pas
#endif /* RGFW_NO_PASSTHROUGH */
RGFW_bool RGFW_FUNC(RGFW_window_setIconEx) (RGFW_window* win, u8* data_src, i32 w, i32 h, RGFW_format format, RGFW_icon type) {
- Atom _NET_WM_ICON = XInternAtom(_RGFW->display, "_NET_WM_ICON", False);
RGFW_ASSERT(win != NULL);
if (data_src == NULL) {
RGFW_bool res = (RGFW_bool)XChangeProperty(
- _RGFW->display, win->src.window, _NET_WM_ICON, XA_CARDINAL, 32,
+ _RGFW->display, win->src.window, _RGFW->_NET_WM_ICON, XA_CARDINAL, 32,
PropModeReplace, (u8*)NULL, 0
);
return res;
@@ -7437,7 +8228,7 @@ RGFW_bool RGFW_FUNC(RGFW_window_setIconEx) (RGFW_window* win, u8* data_src, i32
RGFW_bool res = RGFW_TRUE;
if (type & RGFW_iconTaskbar) {
res = (RGFW_bool)XChangeProperty(
- _RGFW->display, win->src.window, _NET_WM_ICON, XA_CARDINAL, 32,
+ _RGFW->display, win->src.window, _RGFW->_NET_WM_ICON, XA_CARDINAL, 32,
PropModeReplace, (u8*)data, count
);
}
@@ -7498,9 +8289,9 @@ RGFW_mouse* RGFW_FUNC(RGFW_createMouseStandard) (RGFW_mouseIcon mouse) {
}
RGFW_mouse* RGFW_FUNC(RGFW_createMouse) (u8* data, i32 w, i32 h, RGFW_format format) {
- RGFW_ASSERT(data);
+ RGFW_ASSERT(_RGFW && "An RGFW context must be initialized using RGFW_init and/or set with RGFW_setInfo");
+ RGFW_ASSERT(data);
#ifndef RGFW_NO_X11_CURSOR
- RGFW_init();
XcursorImage* native = XcursorImageCreate((i32)w, (i32)h);
native->xhot = 0;
native->yhot = 0;
@@ -7553,9 +8344,8 @@ void RGFW_FUNC(RGFW_window_hide)(RGFW_window* win) {
XFlush(_RGFW->display);
}
-void RGFW_FUNC(RGFW_window_show) (RGFW_window* win) {
+void RGFW_FUNC(RGFW_window_showPlatform) (RGFW_window* win) {
win->internal.flags &= ~(u32)RGFW_windowHide;
- if (win->internal.flags & RGFW_windowFocusOnShow) RGFW_window_focus(win);
if (RGFW_window_isHidden(win) == RGFW_FALSE) {
return;
@@ -7565,7 +8355,7 @@ void RGFW_FUNC(RGFW_window_show) (RGFW_window* win) {
RGFW_window_move(win, win->x, win->y);
RGFW_waitForShowEvent_X11(win);
- RGFW_window_setFullscreen(win, RGFW_window_isFullscreen(win));
+ RGFW_window_setFullscreenPlatform(win, RGFW_window_isFullscreen(win));
return;
}
@@ -7580,7 +8370,7 @@ void RGFW_FUNC(RGFW_window_flash) (RGFW_window* win, RGFW_flashRequest request)
if (request) {
wmhints->flags |= XUrgencyHint;
if (request == RGFW_flashBriefly)
- win->src.flashEnd = RGFW_linux_getTimeNS() + (u64)1e+9;
+ win->src.flashEnd = RGFW_unix_getTimeNS() + (u64)1e+9;
if (request == RGFW_flashUntilFocused)
win->src.flashEnd = (u64)-1;
} else {
@@ -7592,56 +8382,68 @@ void RGFW_FUNC(RGFW_window_flash) (RGFW_window* win, RGFW_flashRequest request)
XFree(wmhints);
}
-RGFW_ssize_t RGFW_FUNC(RGFW_readClipboardPtr)(char* str, size_t strCapacity) {
- RGFW_init();
- RGFW_LOAD_ATOM(XSEL_DATA); RGFW_LOAD_ATOM(UTF8_STRING); RGFW_LOAD_ATOM(CLIPBOARD);
- if (XGetSelectionOwner(_RGFW->display, CLIPBOARD) == _RGFW->helperWindow) {
- if (str != NULL)
- RGFW_STRNCPY(str, _RGFW->clipboard, _RGFW->clipboard_len - 1);
- _RGFW->clipboard[_RGFW->clipboard_len - 1] = '\0';
- return (RGFW_ssize_t)_RGFW->clipboard_len - 1;
+RGFW_bool RGFW_FUNC(RGFW_readClipboardPtr) (RGFW_dataTransferType requestedType, u8* buffer, size_t capacity, RGFW_dataTransfer* dataTransfer) {
+ RGFW_ASSERT(_RGFW && "An RGFW context must be initialized using RGFW_init and/or set with RGFW_setInfo");
+ RGFW_ASSERT(dataTransfer != NULL);
+
+ if (requestedType != RGFW_dataText) return RGFW_FALSE;
+ dataTransfer->data = (char*)buffer;
+
+ if (XGetSelectionOwner(_RGFW->display, _RGFW->CLIPBOARD) == _RGFW->helperWindow) {
+ dataTransfer->length = _RGFW->unixClipboard->length;
+ if (buffer != NULL && _RGFW->unixClipboard->data != NULL) {
+ if (_RGFW->unixClipboard->length > capacity) return RGFW_FALSE;
+
+ RGFW_MEMCPY((char*)buffer, _RGFW->unixClipboard->data, _RGFW->unixClipboard->length);
+ }
+
+ dataTransfer->type = RGFW_dataText;
+ return RGFW_TRUE;
}
XEvent event;
int format;
- unsigned long N, sizeN;
+ unsigned long N, size;
char* data;
Atom target;
- XConvertSelection(_RGFW->display, CLIPBOARD, UTF8_STRING, XSEL_DATA, _RGFW->helperWindow, CurrentTime);
+ XConvertSelection(_RGFW->display, _RGFW->CLIPBOARD, _RGFW->UTF8_STRING, _RGFW->XSEL_DATA, _RGFW->helperWindow, CurrentTime);
XSync(_RGFW->display, 0);
while (1) {
XNextEvent(_RGFW->display, &event);
if (event.type != SelectionNotify) continue;
- if (event.xselection.selection != CLIPBOARD || event.xselection.property == 0)
- return -1;
+ if (event.xselection.selection != _RGFW->CLIPBOARD || event.xselection.property == 0)
+ return RGFW_FALSE;
break;
}
XGetWindowProperty(event.xselection.display, event.xselection.requestor,
event.xselection.property, 0L, (~0L), 0, AnyPropertyType, &target,
- &format, &sizeN, &N, (u8**) &data);
+ &format, &size, &N, (u8**) &data);
+
+ RGFW_bool ret = RGFW_TRUE;
- RGFW_ssize_t size;
- if (sizeN > strCapacity && str != NULL)
- size = -1;
+ size_t length = size;
+ if (data[size - 1] != '\0') length += 1;
+
+ if (size > capacity && buffer != NULL)
+ ret = RGFW_FALSE;
+ else if ((target == _RGFW->UTF8_STRING || target == XA_STRING) && buffer != NULL) {
+ RGFW_MEMCPY(buffer, data, size);
+ buffer[length - 1] = '\0';
- if ((target == UTF8_STRING || target == XA_STRING) && str != NULL) {
- RGFW_MEMCPY(str, data, sizeN);
- str[sizeN] = '\0';
XFree(data);
- } else if (str != NULL) size = -1;
+ } else if (buffer != NULL) ret = RGFW_FALSE;
XDeleteProperty(event.xselection.display, event.xselection.requestor, event.xselection.property);
- size = (RGFW_ssize_t)sizeN;
- return size;
+ dataTransfer->length = length;
+ dataTransfer->type = RGFW_dataText;
+ return ret;
}
i32 RGFW_XHandleClipboardSelectionHelper(void) {
- RGFW_LOAD_ATOM(SAVE_TARGETS);
-
XEvent event;
XPending(_RGFW->display);
@@ -7655,7 +8457,7 @@ i32 RGFW_XHandleClipboardSelectionHelper(void) {
RGFW_XHandleClipboardSelection(&event);
return 0;
case SelectionNotify:
- if (event.xselection.target == SAVE_TARGETS)
+ if (event.xselection.target == _RGFW->SAVE_TARGETS)
return 0;
break;
default: break;
@@ -7664,27 +8466,37 @@ i32 RGFW_XHandleClipboardSelectionHelper(void) {
return 0;
}
-void RGFW_FUNC(RGFW_writeClipboard)(const char* text, u32 textLen) {
- RGFW_LOAD_ATOM(SAVE_TARGETS); RGFW_LOAD_ATOM(CLIPBOARD);
- RGFW_init();
+RGFW_bool RGFW_FUNC(RGFW_writeClipboard)(const RGFW_dataTransfer* data) {
+ RGFW_ASSERT(_RGFW && "An RGFW context must be initialized using RGFW_init and/or set with RGFW_setInfo");
/* request ownership of the clipboard section and request to convert it, this means its our job to convert it */
- XSetSelectionOwner(_RGFW->display, CLIPBOARD, _RGFW->helperWindow, CurrentTime);
- if (XGetSelectionOwner(_RGFW->display, CLIPBOARD) != _RGFW->helperWindow) {
+ XSetSelectionOwner(_RGFW->display, _RGFW->CLIPBOARD, _RGFW->helperWindow, CurrentTime);
+ if (XGetSelectionOwner(_RGFW->display, _RGFW->CLIPBOARD) != _RGFW->helperWindow) {
RGFW_debugCallback(RGFW_typeError, RGFW_errClipboard, "X11 failed to become owner of clipboard selection");
- return;
+ return RGFW_FALSE;
}
- if (_RGFW->clipboard)
- RGFW_FREE(_RGFW->clipboard);
+ if (_RGFW->unixClipboard) {
+ RGFW_FREE(_RGFW->unixClipboard);
+ _RGFW->unixClipboard = NULL;
+ }
- _RGFW->clipboard = (char*)RGFW_ALLOC(textLen);
- RGFW_ASSERT(_RGFW->clipboard != NULL);
+ size_t length = data->length;
+ if (data->data[data->length - 1] != '\0') {
+ length += 1;
+ }
- RGFW_STRNCPY(_RGFW->clipboard, text, textLen - 1);
- _RGFW->clipboard[textLen - 1] = '\0';
- _RGFW->clipboard_len = textLen;
- return;
+ _RGFW->unixClipboard = (RGFW_dataTransfer*)RGFW_ALLOC(sizeof(RGFW_dataTransfer) + data->length);
+ RGFW_ASSERT(_RGFW->unixClipboard != NULL);
+
+ char* data_ptr = &((char*)(void*)_RGFW->unixClipboard)[sizeof(RGFW_dataTransfer) - 1];
+ RGFW_MEMCPY(data_ptr, data->data, data->length);
+ data_ptr[length - 1] = '\0';
+
+ _RGFW->unixClipboard->data = (const char*)data_ptr;
+ _RGFW->unixClipboard->type = RGFW_dataText;
+ _RGFW->unixClipboard->length = length;
+ return RGFW_TRUE;
}
RGFW_bool RGFW_FUNC(RGFW_window_isHidden)(RGFW_window* win) {
@@ -7697,14 +8509,13 @@ RGFW_bool RGFW_FUNC(RGFW_window_isHidden)(RGFW_window* win) {
RGFW_bool RGFW_FUNC(RGFW_window_isMinimized)(RGFW_window* win) {
RGFW_ASSERT(win != NULL);
- RGFW_LOAD_ATOM(WM_STATE);
Atom actual_type;
i32 actual_format;
unsigned long nitems, bytes_after;
unsigned char* prop_data;
- i32 status = XGetWindowProperty(_RGFW->display, win->src.window, WM_STATE, 0, 2, False,
+ i32 status = XGetWindowProperty(_RGFW->display, win->src.window, _RGFW->WM_STATE, 0, 2, False,
AnyPropertyType, &actual_type, &actual_format,
&nitems, &bytes_after, &prop_data);
@@ -7723,16 +8534,13 @@ RGFW_bool RGFW_FUNC(RGFW_window_isMinimized)(RGFW_window* win) {
RGFW_bool RGFW_FUNC(RGFW_window_isMaximized)(RGFW_window* win) {
RGFW_ASSERT(win != NULL);
- RGFW_LOAD_ATOM(_NET_WM_STATE);
- RGFW_LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
- RGFW_LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
Atom actual_type;
i32 actual_format;
unsigned long nitems, bytes_after;
unsigned char* prop_data;
- i32 status = XGetWindowProperty(_RGFW->display, win->src.window, _NET_WM_STATE, 0, 1024, False,
+ i32 status = XGetWindowProperty(_RGFW->display, win->src.window, _RGFW->_NET_WM_STATE, 0, 1024, False,
XA_ATOM, &actual_type, &actual_format,
&nitems, &bytes_after, &prop_data);
@@ -7745,8 +8553,8 @@ RGFW_bool RGFW_FUNC(RGFW_window_isMaximized)(RGFW_window* win) {
u64 i;
for (i = 0; i < nitems; i++) {
- if (prop_data[i] == _NET_WM_STATE_MAXIMIZED_VERT ||
- prop_data[i] == _NET_WM_STATE_MAXIMIZED_HORZ) {
+ if (prop_data[i] == _RGFW->_NET_WM_STATE_MAXIMIZED_VERT ||
+ prop_data[i] == _RGFW->_NET_WM_STATE_MAXIMIZED_HORZ) {
XFree(prop_data);
return RGFW_TRUE;
}
@@ -7763,20 +8571,18 @@ void RGFW_XGetSystemContentDPI(float* dpi) {
if (dpi == NULL) return;
float dpiOutput = 96.0f;
- #ifndef RGFW_NO_XRANDR
- char* rms = XResourceManagerString(_RGFW->display);
- if (rms == NULL) return;
+ char* rms = XResourceManagerString(_RGFW->display);
+ if (rms == NULL) return;
- XrmDatabase db = XrmGetStringDatabase(rms);
- if (db == NULL) return;
+ XrmDatabase db = XrmGetStringDatabase(rms);
+ if (db == NULL) return;
- XrmValue value;
- char* type = NULL;
+ XrmValue value;
+ char* type = NULL;
- if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value) && type && RGFW_STRNCMP(type, "String", 7) == 0)
- dpiOutput = (float)RGFW_ATOF(value.addr);
- XrmDestroyDatabase(db);
- #endif
+ if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value) && type && RGFW_STRNCMP(type, "String", 7) == 0)
+ dpiOutput = (float)RGFW_ATOF(value.addr);
+ XrmDestroyDatabase(db);
if (dpi) *dpi = dpiOutput;
}
@@ -7836,7 +8642,7 @@ XRRModeInfo* RGFW_XGetMode(XRRCrtcInfo* ci, XRRScreenResources* res, RRMode mode
}
void RGFW_FUNC(RGFW_pollMonitors) (void) {
- RGFW_init();
+ RGFW_ASSERT(_RGFW && "An RGFW context must be initialized using RGFW_init and/or set with RGFW_setInfo");
Window root = XDefaultRootWindow(_RGFW->display);
XRRScreenResources* res = XRRGetScreenResourcesCurrent(_RGFW->display, root);
@@ -7858,14 +8664,6 @@ void RGFW_FUNC(RGFW_pollMonitors) (void) {
}
}
- if (node) {
- node->disconnected = RGFW_FALSE;
- if (node->rrOutput == primary) {
- _RGFW->monitors.primary = node;
- }
- continue;
- }
-
RGFW_monitor monitor;
XRROutputInfo* info = XRRGetOutputInfo(_RGFW->display, res, res->outputs[i]);
@@ -7914,20 +8712,32 @@ void RGFW_FUNC(RGFW_pollMonitors) (void) {
XRRFreeCrtcInfo(ci);
- node = RGFW_monitors_add(&monitor);
- if (node == NULL) break;
-
- node->rrOutput = res->outputs[i];
- node->crtc = info->crtc;
-
- if (node->rrOutput == primary) {
- _RGFW->monitors.primary = node;
- }
+ RROutput rrOutput = res->outputs[i];
+ RRCrtc crtc = info->crtc;
XRRFreeOutputInfo(info);
info = NULL;
- RGFW_monitorCallback(_RGFW->root, &node->mon, RGFW_TRUE);
+ if (node) {
+ node->disconnected = RGFW_FALSE;
+ if (node->rrOutput == primary) {
+ _RGFW->monitors.primary = node;
+ }
+
+ continue;
+ } else {
+ node = RGFW_monitors_add(&monitor);
+ if (node == NULL) break;
+
+ node->rrOutput = rrOutput;
+ node->crtc = crtc;
+
+ if (node->rrOutput == primary) {
+ _RGFW->monitors.primary = node;
+ }
+
+ RGFW_monitorCallback(_RGFW->root, &node->mon, RGFW_TRUE);
+ }
}
XRRFreeScreenResources(res);
@@ -7935,10 +8745,12 @@ void RGFW_FUNC(RGFW_pollMonitors) (void) {
RGFW_monitors_refresh();
}
-RGFW_bool RGFW_FUNC(RGFW_monitor_getWorkarea) (RGFW_monitor* monitor, i32* x, i32* y, i32* width, i32* height) {
- RGFW_LOAD_ATOM(_NET_WORKAREA);
- RGFW_LOAD_ATOM(_NET_CURRENT_DESKTOP);
+void RGFW_FUNC(RGFW_monitorNode_free) (RGFW_monitorNode* node) {
+ RGFW_ASSERT(node);
+}
+RGFW_bool RGFW_FUNC(RGFW_monitor_getWorkarea) (RGFW_monitor* monitor, i32* x, i32* y, i32* width, i32* height) {
+ RGFW_ASSERT(monitor != NULL);
Window root = DefaultRootWindow(_RGFW->display);
i32 areaX = monitor->x;
@@ -7946,17 +8758,17 @@ RGFW_bool RGFW_FUNC(RGFW_monitor_getWorkarea) (RGFW_monitor* monitor, i32* x, i3
i32 areaW = monitor->mode.w;
i32 areaH = monitor->mode.h;
- if (_NET_WORKAREA && _NET_CURRENT_DESKTOP) {
+ if (_RGFW->_NET_WORKAREA && _RGFW->_NET_CURRENT_DESKTOP) {
Atom* extents = NULL;
Atom* desktop = NULL;
Atom actualType = 0;
int actualFormat = 0;
unsigned long extentCount = 0, bytesAfter = 0;
- XGetWindowProperty(_RGFW->display, root, _NET_WORKAREA, 0, LONG_MAX, False, XA_CARDINAL, &actualType, &actualFormat, &extentCount, &bytesAfter, (u8**) &extents);
+ XGetWindowProperty(_RGFW->display, root, _RGFW->_NET_WORKAREA, 0, LONG_MAX, False, XA_CARDINAL, &actualType, &actualFormat, &extentCount, &bytesAfter, (u8**) &extents);
unsigned long count;
- XGetWindowProperty(_RGFW->display, root, _NET_CURRENT_DESKTOP, 0, LONG_MAX, False, XA_CARDINAL, &actualType, &actualFormat, &count, &bytesAfter, (u8**) &desktop);
+ XGetWindowProperty(_RGFW->display, root, _RGFW->_NET_CURRENT_DESKTOP, 0, LONG_MAX, False, XA_CARDINAL, &actualType, &actualFormat, &count, &bytesAfter, (u8**) &desktop);
if (count) {
if (extentCount >= 4 && *desktop < extentCount / 4) {
@@ -7997,6 +8809,7 @@ RGFW_bool RGFW_FUNC(RGFW_monitor_getWorkarea) (RGFW_monitor* monitor, i32* x, i3
}
size_t RGFW_FUNC(RGFW_monitor_getModesPtr) (RGFW_monitor* monitor, RGFW_monitorMode** modes) {
+ RGFW_ASSERT(monitor != NULL);
size_t count = 0;
XRRScreenResources* res = XRRGetScreenResourcesCurrent(_RGFW->display, DefaultRootWindow(_RGFW->display));
@@ -8020,8 +8833,8 @@ size_t RGFW_FUNC(RGFW_monitor_getModesPtr) (RGFW_monitor* monitor, RGFW_monitorM
}
size_t RGFW_FUNC(RGFW_monitor_getGammaRampPtr) (RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
+ RGFW_ASSERT(monitor != NULL);
RGFW_UNUSED(monitor); RGFW_UNUSED(ramp);
-#ifndef RGFW_NO_XRANDR
size_t size = (size_t)XRRGetCrtcGammaSize(_RGFW->display, monitor->node->crtc);
XRRCrtcGamma* gamma = XRRGetCrtcGamma(_RGFW->display, monitor->node->crtc);
@@ -8033,15 +8846,12 @@ size_t RGFW_FUNC(RGFW_monitor_getGammaRampPtr) (RGFW_monitor* monitor, RGFW_gamm
XRRFreeGamma(gamma);
return size;
-#endif
-
- return 0;
}
RGFW_bool RGFW_FUNC(RGFW_monitor_setGammaRamp) (RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
+ RGFW_ASSERT(monitor != NULL);
RGFW_UNUSED(monitor); RGFW_UNUSED(ramp);
-#ifndef RGFW_NO_XRANDR
size_t size = (size_t)XRRGetCrtcGammaSize(_RGFW->display, monitor->node->crtc);
if (size != ramp->count) {
RGFW_debugCallback(RGFW_typeError, RGFW_errX11, "X11: Gamma ramp size must match current ramp size");
@@ -8058,18 +8868,18 @@ RGFW_bool RGFW_FUNC(RGFW_monitor_setGammaRamp) (RGFW_monitor* monitor, RGFW_gamm
XRRFreeGamma(gamma);
return RGFW_TRUE;
-#endif
- return RGFW_FALSE;
}
RGFW_bool RGFW_FUNC(RGFW_monitor_setMode)(RGFW_monitor* mon, RGFW_monitorMode* mode) {
+ RGFW_ASSERT(mon != NULL);
RGFW_bool out = RGFW_FALSE;
XRRScreenResources* res = XRRGetScreenResourcesCurrent(_RGFW->display, DefaultRootWindow(_RGFW->display));
XRRCrtcInfo* ci = XRRGetCrtcInfo(_RGFW->display, res, mon->node->crtc);
- if (XRRSetCrtcConfig(_RGFW->display, res, mon->node->crtc, CurrentTime, ci->x, ci->y, (RRMode)mode->src, ci->rotation, ci->outputs, ci->noutput) == True) {
+ if (XRRSetCrtcConfig(_RGFW->display, res, mon->node->crtc, CurrentTime, ci->x, ci->y, (RRMode)mode->src, ci->rotation, ci->outputs, ci->noutput) == 0) {
out = RGFW_TRUE;
+ mon->mode = *mode;
}
XRRFreeCrtcInfo(ci);
@@ -8078,8 +8888,8 @@ RGFW_bool RGFW_FUNC(RGFW_monitor_setMode)(RGFW_monitor* mon, RGFW_monitorMode* m
}
RGFW_bool RGFW_FUNC(RGFW_monitor_requestMode)(RGFW_monitor* mon, RGFW_monitorMode* mode, RGFW_modeRequest request) {
- #ifndef RGFW_NO_XRANDR
- RGFW_init();
+ RGFW_ASSERT(mon != NULL);
+ RGFW_ASSERT(_RGFW && "An RGFW context must be initialized using RGFW_init and/or set with RGFW_setInfo");
RGFW_bool output = RGFW_FALSE;
@@ -8115,8 +8925,6 @@ RGFW_bool RGFW_FUNC(RGFW_monitor_requestMode)(RGFW_monitor* mon, RGFW_monitorMod
XRRFreeCrtcInfo(ci);
XRRFreeScreenResources(res);
return output;
-#endif
- return RGFW_FALSE;
}
RGFW_monitor* RGFW_FUNC(RGFW_window_getMonitor) (RGFW_window* win) {
@@ -8137,7 +8945,9 @@ RGFW_monitor* RGFW_FUNC(RGFW_window_getMonitor) (RGFW_window* win) {
}
#ifdef RGFW_OPENGL
-RGFW_bool RGFW_FUNC(RGFW_window_createContextPtr_OpenGL) (RGFW_window* win, RGFW_glContext* context, RGFW_glHints* hints) {
+RGFW_bool RGFW_FUNC(RGFW_createContextPtr_OpenGL) (RGFW_glContext* context, RGFW_glHints* hints) {
+ RGFW_ASSERT(_RGFW); RGFW_ASSERT(context); RGFW_ASSERT(hints);
+
/* for checking extensions later */
const char sRGBARBstr[] = "GLX_ARB_framebuffer_sRGB";
const char sRGBEXTstr[] = "GLX_EXT_framebuffer_sRGB";
@@ -8145,18 +8955,8 @@ RGFW_bool RGFW_FUNC(RGFW_window_createContextPtr_OpenGL) (RGFW_window* win, RGFW
const char flushStr[] = "GLX_ARB_context_flush_control";
const char robustStr[] = "GLX_ARB_create_context_robustness";
- /* basic RGFW int */
- win->src.ctx.native = context;
- win->src.gfxType = RGFW_gfxNativeOpenGL;
-
/* This is required so that way the user can create their own OpenGL context after RGFW_createWindow is used */
- RGFW_bool showWindow = RGFW_FALSE;
- if (win->src.window) {
- showWindow = (RGFW_window_isMinimized(win) == RGFW_FALSE);
- RGFW_window_closePlatform(win);
- }
-
- RGFW_bool transparent = (win->internal.flags & RGFW_windowTransparent);
+ RGFW_bool transparent = (hints->depth == 32);
/* start by creating a GLX config / X11 Viusal */
XVisualInfo visual;
@@ -8194,7 +8994,8 @@ RGFW_bool RGFW_FUNC(RGFW_window_createContextPtr_OpenGL) (RGFW_window* win, RGFW
/* find the configs */
i32 fbcount;
- GLXFBConfig* fbc = glXChooseFBConfig(_RGFW->display, DefaultScreen(_RGFW->display), visual_attribs, &fbcount);
+ GLXFBConfig* fbc = RGFW_glXChooseFBConfig(_RGFW->display, DefaultScreen(_RGFW->display), visual_attribs, &fbcount);
+ if (fbc == NULL) return RGFW_FALSE;
i32 best_fbc = -1;
i32 best_depth = 0;
@@ -8208,13 +9009,13 @@ RGFW_bool RGFW_FUNC(RGFW_window_createContextPtr_OpenGL) (RGFW_window* win, RGFW
/* search through all found configs to find the best match */
i32 i;
for (i = 0; i < fbcount; i++) {
- XVisualInfo* vi = glXGetVisualFromFBConfig(_RGFW->display, fbc[i]);
+ XVisualInfo* vi = RGFW_glXGetVisualFromFBConfig(_RGFW->display, fbc[i]);
if (vi == NULL)
continue;
i32 samp_buf, samples;
- glXGetFBConfigAttrib(_RGFW->display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf);
- glXGetFBConfigAttrib(_RGFW->display, fbc[i], GLX_SAMPLES, &samples);
+ RGFW_glXGetFBConfigAttrib(_RGFW->display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf);
+ RGFW_glXGetFBConfigAttrib(_RGFW->display, fbc[i], GLX_SAMPLES, &samples);
if (best_fbc == -1) best_fbc = i;
if ((!(transparent) || vi->depth == 32) && best_depth == 0) {
@@ -8236,32 +9037,22 @@ RGFW_bool RGFW_FUNC(RGFW_window_createContextPtr_OpenGL) (RGFW_window* win, RGFW
/* we found a config */
bestFbc = fbc[best_fbc];
- XVisualInfo* vi = glXGetVisualFromFBConfig(_RGFW->display, bestFbc);
- if (vi->depth != 32 && transparent)
- RGFW_debugCallback(RGFW_typeWarning, RGFW_warningOpenGL, "Failed to to find a matching visual with a 32-bit depth.");
+ context->config = bestFbc;
if (best_samples < hints->samples)
RGFW_debugCallback(RGFW_typeWarning, RGFW_warningOpenGL, "Failed to load a matching sample count.");
XFree(fbc);
- visual = *vi;
- XFree(vi);
-
- /* use the visual to create a new window */
- RGFW_XCreateWindow(visual, "", win->internal.flags, win);
-
- if (showWindow) {
- RGFW_window_show(win);
- }
/* create the actual OpenGL context */
i32 context_attribs[40];
RGFW_attribStack_init(&stack, context_attribs, 40);
i32 mask = 0;
+ i32 flags = 0;
+
switch (hints->profile) {
case RGFW_glES: mask |= GLX_CONTEXT_ES_PROFILE_BIT_EXT; break;
- case RGFW_glForwardCompatibility: mask |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; break;
case RGFW_glCompatibility: mask |= GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; break;
case RGFW_glCore: mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB; break;
default: mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB; break;
@@ -8269,12 +9060,18 @@ RGFW_bool RGFW_FUNC(RGFW_window_createContextPtr_OpenGL) (RGFW_window* win, RGFW
RGFW_attribStack_pushAttribs(&stack, GLX_CONTEXT_PROFILE_MASK_ARB, mask);
+ if (hints->profile == RGFW_glForwardCompatibility) flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
+ if (hints->debug) flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
+ if (hints->robustness && RGFW_extensionSupportedPlatform_OpenGL(robustStr, sizeof(robustStr))) flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
+ if (flags) {
+ RGFW_attribStack_pushAttribs(&stack, GLX_CONTEXT_FLAGS_ARB, flags);
+ }
+
if (hints->minor || hints->major) {
RGFW_attribStack_pushAttribs(&stack, GLX_CONTEXT_MAJOR_VERSION_ARB, hints->major);
RGFW_attribStack_pushAttribs(&stack, GLX_CONTEXT_MINOR_VERSION_ARB, hints->minor);
}
-
if (RGFW_extensionSupportedPlatform_OpenGL(flushStr, sizeof(flushStr))) {
if (hints->releaseBehavior == RGFW_glReleaseFlush) {
RGFW_attribStack_pushAttribs(&stack, GLX_CONTEXT_RELEASE_BEHAVIOR_ARB, GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
@@ -8283,13 +9080,6 @@ RGFW_bool RGFW_FUNC(RGFW_window_createContextPtr_OpenGL) (RGFW_window* win, RGFW
}
}
- i32 flags = 0;
- if (hints->debug) flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
- if (hints->robustness && RGFW_extensionSupportedPlatform_OpenGL(robustStr, sizeof(robustStr))) flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
- if (flags) {
- RGFW_attribStack_pushAttribs(&stack, GLX_CONTEXT_FLAGS_ARB, flags);
- }
-
if (RGFW_extensionSupportedPlatform_OpenGL(noErorrStr, sizeof(noErorrStr))) {
RGFW_attribStack_pushAttribs(&stack, GLX_CONTEXT_OPENGL_NO_ERROR_ARB, hints->noError);
}
@@ -8297,111 +9087,207 @@ RGFW_bool RGFW_FUNC(RGFW_window_createContextPtr_OpenGL) (RGFW_window* win, RGFW
RGFW_attribStack_pushAttribs(&stack, 0, 0);
/* create the context */
- glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
- char str[] = "glXCreateContextAttribsARB";
- glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddressARB((u8*) str);
-
GLXContext ctx = NULL;
if (hints->share) {
ctx = hints->share->ctx;
}
- if (glXCreateContextAttribsARB == NULL) {
+ if (RGFW_glXCreateContextAttribsARB == NULL) {
RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to load proc address 'glXCreateContextAttribsARB', loading a generic OpenGL context.");
- win->src.ctx.native->ctx = glXCreateContext(_RGFW->display, &visual, ctx, True);
+ context->ctx = RGFW_glXCreateContext(_RGFW->display, &visual, ctx, True);
} else {
_RGFW->x11Error = NULL;
- win->src.ctx.native->ctx = glXCreateContextAttribsARB(_RGFW->display, bestFbc, ctx, True, context_attribs);
- if (_RGFW->x11Error || win->src.ctx.native->ctx == NULL) {
+ context->ctx = RGFW_glXCreateContextAttribsARB(_RGFW->display, bestFbc, ctx, True, context_attribs);
+ if (_RGFW->x11Error || context->ctx == NULL) {
RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to create an OpenGL context with AttribsARB, loading a generic OpenGL context.");
- win->src.ctx.native->ctx = glXCreateContext(_RGFW->display, &visual, ctx, True);
+ context->ctx = RGFW_glXCreateContext(_RGFW->display, &visual, ctx, True);
+ }
+ }
+
+ RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context initalized.");
+ return RGFW_TRUE;
+}
+
+void RGFW_FUNC(RGFW_deleteContextPtr_OpenGL) (RGFW_glContext* ctx) {
+ RGFW_glXDestroyContext(_RGFW->display, ctx->ctx);
+ RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context freed.");
+}
+
+RGFW_bool RGFW_FUNC(RGFW_window_setContext_OpenGL) (RGFW_window* win, RGFW_glContext* context) {
+ RGFW_ASSERT(win);
+
+ if (context == NULL && win->src.ctx.native != NULL) {
+ #ifndef RGFW_NO_GLXWINDOW
+ if (win->src.ctx.native->window != win->src.window) {
+ RGFW_glXDestroyWindow(_RGFW->display, win->src.ctx.native->window);
}
+ #endif
+
+ win->src.ctx.native = NULL;
+ RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL surface freed.");
+ return RGFW_TRUE;
+ }
+
+ /* basic RGFW int */
+ win->src.ctx.native = context;
+ win->src.gfxType = RGFW_gfxNativeOpenGL;
+
+ /* This is required so that way the user can create their own OpenGL context after RGFW_createWindow is used */
+ RGFW_bool showWindow = RGFW_FALSE;
+
+ char* name = NULL;
+ if (win->src.window) {
+ showWindow = (RGFW_window_isMinimized(win) == RGFW_FALSE);
+ name = RGFW_XGetWindowName(win->src.window);
+ RGFW_window_closePlatform(win);
+ }
+
+ XVisualInfo* vi = RGFW_glXGetVisualFromFBConfig(_RGFW->display, (GLXFBConfig)context->config);
+
+ /* use the visual to create a new window */
+ if (RGFW_XCreateWindow(*vi, name ? name : "", win->internal.flags, win) == RGFW_FALSE) return RGFW_FALSE;
+ if (name != NULL) XFree(name);
+
+ if (showWindow) {
+ RGFW_window_show(win);
}
#ifndef RGFW_NO_GLXWINDOW
- win->src.ctx.native->window = glXCreateWindow(_RGFW->display, bestFbc, win->src.window, NULL);
+ win->src.ctx.native->window = RGFW_glXCreateWindow(_RGFW->display, (GLXFBConfig)context->config, win->src.window, NULL);
#else
win->src.ctx.native->window = win->src.window;
#endif
- glXMakeCurrent(_RGFW->display, (Drawable)win->src.ctx.native->window, (GLXContext)win->src.ctx.native->ctx);
- RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context initalized.");
+ RGFW_glXMakeCurrent(_RGFW->display, (Drawable)win->src.ctx.native->window, (GLXContext)win->src.ctx.native->ctx);
+ RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL surface initalized.");
RGFW_window_swapInterval_OpenGL(win, 0);
return RGFW_TRUE;
}
-void RGFW_FUNC(RGFW_window_deleteContextPtr_OpenGL) (RGFW_window* win, RGFW_glContext* ctx) {
- #ifndef RGFW_NO_GLXWINDOW
- if (win->src.ctx.native->window != win->src.window) {
- glXDestroyWindow(_RGFW->display, win->src.ctx.native->window);
- }
- #endif
-
- glXDestroyContext(_RGFW->display, ctx->ctx);
- win->src.ctx.native = NULL;
- RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context freed.");
-}
-
RGFW_bool RGFW_FUNC(RGFW_extensionSupportedPlatform_OpenGL)(const char * extension, size_t len) {
- RGFW_init();
- const char* extensions = glXQueryExtensionsString(_RGFW->display, XDefaultScreen(_RGFW->display));
+ RGFW_ASSERT(_RGFW && "An RGFW context must be initialized using RGFW_init and/or set with RGFW_setInfo");
+ const char* extensions = RGFW_glXQueryExtensionsString(_RGFW->display, XDefaultScreen(_RGFW->display));
return (extensions != NULL) && RGFW_extensionSupportedStr(extensions, extension, len);
}
-RGFW_proc RGFW_FUNC(RGFW_getProcAddress_OpenGL)(const char* procname) { return glXGetProcAddress((u8*) procname); }
+RGFW_proc RGFW_FUNC(RGFW_getProcAddress_OpenGL)(const char* procname) { return _RGFW->glGetProcAddress((const char*) procname); }
void RGFW_FUNC(RGFW_window_makeCurrentContext_OpenGL) (RGFW_window* win) { if (win) RGFW_ASSERT(win->src.ctx.native);
if (win == NULL)
- glXMakeCurrent(NULL, (Drawable)NULL, (GLXContext) NULL);
+ RGFW_glXMakeCurrent(NULL, (Drawable)NULL, (GLXContext) NULL);
else
- glXMakeCurrent(_RGFW->display, (Drawable)win->src.ctx.native->window, (GLXContext) win->src.ctx.native->ctx);
+ RGFW_glXMakeCurrent(_RGFW->display, (Drawable)win->src.ctx.native->window, (GLXContext) win->src.ctx.native->ctx);
return;
}
-void* RGFW_FUNC(RGFW_getCurrentContext_OpenGL) (void) { return glXGetCurrentContext(); }
-void RGFW_FUNC(RGFW_window_swapBuffers_OpenGL) (RGFW_window* win) { RGFW_ASSERT(win->src.ctx.native); glXSwapBuffers(_RGFW->display, win->src.ctx.native->window); }
+void* RGFW_FUNC(RGFW_getCurrentContext_OpenGL) (void) { return RGFW_glXGetCurrentContext(); }
+void* RGFW_FUNC(RGFW_getCurrentSurface_OpenGL) (void) { return RGFW_glXGetCurrentDrawable(); }
+void RGFW_FUNC(RGFW_window_swapBuffers_OpenGL) (RGFW_window* win) { RGFW_ASSERT(win->src.ctx.native); RGFW_glXSwapBuffers(_RGFW->display, win->src.ctx.native->window); }
void RGFW_FUNC(RGFW_window_swapInterval_OpenGL) (RGFW_window* win, i32 swapInterval) {
RGFW_ASSERT(win != NULL);
- /* cached pfn to avoid calling glXGetProcAddress more than once */
- static PFNGLXSWAPINTERVALEXTPROC pfn = NULL;
- static int (*pfn2)(int) = NULL;
-
- if (pfn == NULL) {
- u8 str[] = "glXSwapIntervalEXT";
- pfn = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddress(str);
- if (pfn == NULL) {
- pfn = (PFNGLXSWAPINTERVALEXTPROC)1;
- const char* array[] = {"GLX_MESA_swap_control", "GLX_SGI_swap_control"};
+ if (RGFW_glXSwapIntervalEXT) {
+ RGFW_glXSwapIntervalEXT(_RGFW->display, win->src.ctx.native->window, swapInterval);
+ } else if (RGFW_GLX_MESA_swap_control || RGFW_GLX_SGI_swap_control) {
+ void* ctx = RGFW_getCurrentContext_OpenGL();
+ void* surf = RGFW_getCurrentSurface_OpenGL();
+ if (ctx != win->src.ctx.native->ctx || (Drawable)surf != win->src.ctx.native->window)
+ RGFW_glXMakeCurrent(_RGFW->display, (Drawable)win->src.ctx.native->window, (GLXContext) win->src.ctx.native->ctx);
- size_t i;
- for (i = 0; i < sizeof(array) / sizeof(char*) && pfn2 == NULL; i++) {
- pfn2 = (int(*)(int))glXGetProcAddress((u8*)array[i]);
- }
-
- if (pfn2 != NULL) {
- RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to load swap interval function, fallingback to the native swapinterval function");
+ if (RGFW_GLX_MESA_swap_control)
+ RGFW_GLX_MESA_swap_control(swapInterval);
+ else if (RGFW_GLX_SGI_swap_control) {
+ if (swapInterval > 0) {
+ RGFW_GLX_SGI_swap_control(swapInterval);
} else {
- RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to load swap interval function");
+ RGFW_debugCallback(RGFW_typeWarning, RGFW_errOpenGLContext, "Failed to disable swap interval, not supported with GLX_SGI_swap_control");
}
}
- }
- if (pfn != (PFNGLXSWAPINTERVALEXTPROC)1) {
- pfn(_RGFW->display, win->src.ctx.native->window, swapInterval);
- }
- else if (pfn2 != NULL) {
- pfn2(swapInterval);
+ if (ctx != win->src.ctx.native->ctx || (Drawable)surf != win->src.ctx.native->window)
+ RGFW_glXMakeCurrent(_RGFW->display, (Drawable)surf, (GLXContext)ctx);
+ } else {
+ RGFW_debugCallback(RGFW_typeWarning, RGFW_errOpenGLContext, "Failed to load swap interval function");
}
}
#endif /* RGFW_OPENGL */
-i32 RGFW_initPlatform_X11(void) {
+i32 RGFW_initPlatform_X11(const char* className, RGFW_initFlags flags) {
+ _RGFW->className = className;
+ RGFW_UNUSED(flags);
+
#ifdef RGFW_USE_XDL
XDL_init();
#endif
+ XInitThreads(); /*!< init X11 threading */
+ _RGFW->display = XOpenDisplay(0);
+
+#ifdef RGFW_X11_DEBUG
+ XSynchronize(_RGFW->display, True);
+#endif
+
+ if (_RGFW->display == NULL) return -1;
+
+ #define RGFW_LOAD_ATOM(name) _RGFW->name = XInternAtom(_RGFW->display, #name, False)
+ RGFW_LOAD_ATOM(_NET_CURRENT_DESKTOP);
+ RGFW_LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
+ RGFW_LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
+ RGFW_LOAD_ATOM(_NET_WM_BYPASS_COMPOSITOR);
+ RGFW_LOAD_ATOM(_NET_WM_STATE);
+ RGFW_LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
+ RGFW_LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
+ RGFW_LOAD_ATOM(_MOTIF_WM_HINTS);
+ RGFW_LOAD_ATOM(WM_DELETE_WINDOW);
+ RGFW_LOAD_ATOM(_NET_WM_SYNC_REQUEST_COUNTER);
+ RGFW_LOAD_ATOM(_NET_WM_SYNC_REQUEST);
+ RGFW_LOAD_ATOM(ATOM_PAIR);
+ RGFW_LOAD_ATOM(MULTIPLE);
+ RGFW_LOAD_ATOM(TARGETS);
+ RGFW_LOAD_ATOM(SAVE_TARGETS);
+ RGFW_LOAD_ATOM(UTF8_STRING);
+ RGFW_LOAD_ATOM(XdndTypeList);
+ RGFW_LOAD_ATOM(XdndSelection);
+ RGFW_LOAD_ATOM(XdndAware);
+ RGFW_LOAD_ATOM(XdndEnter);
+ RGFW_LOAD_ATOM(XdndPosition);
+ RGFW_LOAD_ATOM(XdndStatus);
+ RGFW_LOAD_ATOM(XdndLeave);
+ RGFW_LOAD_ATOM(XdndDrop);
+ RGFW_LOAD_ATOM(XdndFinished);
+ RGFW_LOAD_ATOM(XdndActionCopy);
+ RGFW_LOAD_ATOM(_NET_WM_SYNC_REQUEST);
+ RGFW_LOAD_ATOM(WM_PROTOCOLS);
+ RGFW_LOAD_ATOM(WM_STATE);
+ RGFW_LOAD_ATOM(_NET_WM_STATE);
+ RGFW_LOAD_ATOM(_NET_WM_STATE_FULLSCREEN);
+ RGFW_LOAD_ATOM(_NET_WM_STATE_ABOVE);
+ RGFW_LOAD_ATOM(NET_WM_WINDOW_OPACITY);
+ RGFW_LOAD_ATOM(_NET_WM_STATE);
+ RGFW_LOAD_ATOM(_NET_WM_STATE_ABOVE);
+ RGFW_LOAD_ATOM(_NET_WM_NAME);
+ RGFW_LOAD_ATOM(_NET_WM_ICON);
+ RGFW_LOAD_ATOM(UTF8_STRING);
+ RGFW_LOAD_ATOM(XSEL_DATA);
+ RGFW_LOAD_ATOM(UTF8_STRING);
+ RGFW_LOAD_ATOM(CLIPBOARD);
+ RGFW_LOAD_ATOM(CLIPBOARD_MANAGER);
+ _RGFW->XtextUriList = XInternAtom(_RGFW->display, "text/uri-list", False);
+ _RGFW->XtextPlain = XInternAtom(_RGFW->display, "text/plain", False);
+ #undef RGFW_LOAD_ATOM
+
+ _RGFW->context = XUniqueContext();
+ if (_RGFW->context == 0) return -1;
+
+ XSetWindowAttributes wa;
+ RGFW_MEMZERO(&wa, sizeof(wa));
+ wa.event_mask = PropertyChangeMask;
+ _RGFW->helperWindow = XCreateWindow(_RGFW->display, XDefaultRootWindow(_RGFW->display), 0, 0, 1, 1, 0, 0,
+ InputOnly, DefaultVisual(_RGFW->display, DefaultScreen(_RGFW->display)), CWEventMask, &wa);
+
+ if (_RGFW->helperWindow == 0) return -1;
+
#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)
#if defined(__CYGWIN__)
RGFW_LOAD_LIBRARY(X11Cursorhandle, "libXcursor-1.so");
@@ -8441,25 +9327,17 @@ i32 RGFW_initPlatform_X11(void) {
RGFW_PROC_DEF(X11XEXThandle, XShapeCombineMask);
#endif
- XInitThreads(); /*!< init X11 threading */
- _RGFW->display = XOpenDisplay(0);
- _RGFW->context = XUniqueContext();
-
- XSetWindowAttributes wa;
- RGFW_MEMZERO(&wa, sizeof(wa));
- wa.event_mask = PropertyChangeMask;
- _RGFW->helperWindow = XCreateWindow(_RGFW->display, XDefaultRootWindow(_RGFW->display), 0, 0, 1, 1, 0, 0,
- InputOnly, DefaultVisual(_RGFW->display, DefaultScreen(_RGFW->display)), CWEventMask, &wa);
-
u8 RGFW_blk[] = { 0, 0, 0, 0 };
_RGFW->hiddenMouse = RGFW_createMouse(RGFW_blk, 1, 1, RGFW_formatRGBA8);
- _RGFW->clipboard = NULL;
+ _RGFW->unixClipboard = NULL;
XkbComponentNamesRec rec;
XkbDescPtr desc = XkbGetMap(_RGFW->display, 0, XkbUseCoreKbd);
XkbDescPtr evdesc;
XSetErrorHandler(RGFW_XErrorHandler);
+ XSync(_RGFW->display, False);
+
u8 old[256];
XkbGetNames(_RGFW->display, XkbKeyNamesMask, desc);
@@ -8490,47 +9368,35 @@ i32 RGFW_initPlatform_X11(void) {
XSetLocaleModifiers("");
XRegisterIMInstantiateCallback(_RGFW->display, NULL, NULL, NULL, RGFW_x11_imInitCallback, NULL);
- unsigned char mask[XIMaskLen(XI_RawMotion)];
- RGFW_MEMZERO(mask, sizeof(mask));
- XISetMask(mask, XI_RawMotion);
-
- XIEventMask em;
- em.deviceid = XIAllMasterDevices;
- em.mask_len = sizeof(mask);
- em.mask = mask;
-
- XISelectEvents(_RGFW->display, XDefaultRootWindow(_RGFW->display), &em, 1);
-
-#ifndef RGFW_NO_XRANDR
i32 errorBase;
if (XRRQueryExtension(_RGFW->display, &_RGFW->xrandrEventBase, &errorBase)) {
XRRSelectInput(_RGFW->display, RootWindow(_RGFW->display, DefaultScreen(_RGFW->display)), RROutputChangeNotifyMask);
}
-#endif
return 0;
}
void RGFW_deinitPlatform_X11(void) {
#define RGFW_FREE_LIBRARY(x) if (x != NULL) dlclose(x); x = NULL;
- /* to save the clipboard on the x server after the window is closed */
- RGFW_LOAD_ATOM(CLIPBOARD_MANAGER); RGFW_LOAD_ATOM(CLIPBOARD);
- RGFW_LOAD_ATOM(SAVE_TARGETS);
- if (XGetSelectionOwner(_RGFW->display, CLIPBOARD) == _RGFW->helperWindow) {
- XConvertSelection(_RGFW->display, CLIPBOARD_MANAGER, SAVE_TARGETS, None, _RGFW->helperWindow, CurrentTime);
- while (RGFW_XHandleClipboardSelectionHelper());
- }
- XUnregisterIMInstantiateCallback(_RGFW->display, NULL, NULL, NULL, RGFW_x11_imInitCallback, NULL);
+ if (_RGFW->display != NULL) {
+ /* to save the clipboard on the x server after the window is closed */
+ if (XGetSelectionOwner(_RGFW->display, _RGFW->CLIPBOARD) == _RGFW->helperWindow) {
+ XConvertSelection(_RGFW->display, _RGFW->CLIPBOARD_MANAGER, _RGFW->SAVE_TARGETS, None, _RGFW->helperWindow, CurrentTime);
+ while (RGFW_XHandleClipboardSelectionHelper());
+ }
+
+ XUnregisterIMInstantiateCallback(_RGFW->display, NULL, NULL, NULL, RGFW_x11_imInitCallback, NULL);
+ }
if (_RGFW->im) {
XCloseIM(_RGFW->im);
_RGFW->im = NULL;
}
- if (_RGFW->clipboard) {
- RGFW_FREE(_RGFW->clipboard);
- _RGFW->clipboard = NULL;
+ if (_RGFW->unixClipboard) {
+ RGFW_FREE(_RGFW->unixClipboard);
+ _RGFW->unixClipboard = NULL;
}
if (_RGFW->hiddenMouse) {
@@ -8538,8 +9404,12 @@ void RGFW_deinitPlatform_X11(void) {
_RGFW->hiddenMouse = NULL;
}
- XDestroyWindow(_RGFW->display, (Drawable) _RGFW->helperWindow); /*!< close the window */
- XCloseDisplay(_RGFW->display); /*!< kill connection to the x server */
+ if (_RGFW->helperWindow)
+ XDestroyWindow(_RGFW->display, (Drawable) _RGFW->helperWindow); /*!< close the window */
+
+ if (_RGFW->display)
+ XCloseDisplay(_RGFW->display); /*!< kill connection to the x server */
+ _RGFW->display = NULL;
#if !defined(RGFW_NO_X11_CURSOR_PRELOAD) && !defined(RGFW_NO_X11_CURSOR)
RGFW_FREE_LIBRARY(X11Cursorhandle);
@@ -8584,12 +9454,12 @@ WGPUSurface RGFW_FUNC(RGFW_window_createSurface_WebGPU) (RGFW_window* window, WG
#endif
/*
- End of X11 linux / wayland / unix defines
+ End of *nix
*/
/*
- Start of Wayland defayland
+ Start of Wayland defines
*/
#ifdef RGFW_WAYLAND
@@ -8600,24 +9470,6 @@ WGPUSurface RGFW_FUNC(RGFW_window_createSurface_WebGPU) (RGFW_window* window, WG
#define RGFW_FUNC(func) func
#endif
-/*
-Wayland TODO: (out of date)
-- fix RGFW_keyPressed lock state
-
- RGFW_windowMoved, the window was moved (by the user)
- RGFW_windowRefresh The window content needs to be refreshed
-
- RGFW_dataDrop a file has been dropped into the window
- RGFW_dataDrag
-
-- window args:
- #define RGFW_windowNoResize the window cannot be resized by the user
- #define RGFW_windowAllowDND the window supports drag and drop
- #define RGFW_scaleToMonitor scale the window to the screen
-
-- other missing functions functions ("TODO wayland") (~30 functions)
-- fix buffer rendering weird behavior
-*/
#include <errno.h>
#include <unistd.h>
#include <sys/mman.h>
@@ -8629,10 +9481,13 @@ Wayland TODO: (out of date)
#include <wayland-cursor.h>
#include <fcntl.h>
+#ifndef RGFW_X11
+RGFW_bool RGFW_usingWayland(void) { return RGFW_TRUE; }
+#endif
+
struct wl_display* RGFW_getDisplay_Wayland(void) { return _RGFW->wl_display; }
struct wl_surface* RGFW_window_getWindow_Wayland(RGFW_window* win) { return win->src.surface; }
-
/* wayland global garbage (wayland bad, X11 is fine (ish) (not really)) */
#include "xdg-shell.h"
#include "xdg-toplevel-icon-v1.h"
@@ -8825,7 +9680,7 @@ static void RGFW_wl_pointer_motion(void* data, struct wl_pointer *pointer, u32 t
i32 convertedX = (i32)wl_fixed_to_double(x);
i32 convertedY = (i32)wl_fixed_to_double(y);
- RGFW_mousePosCallback(win, convertedX, convertedY);
+ RGFW_mouseMotionCallback(win, convertedX, convertedY);
}
static void RGFW_wl_pointer_button(void* data, struct wl_pointer *pointer, u32 serial, u32 time, u32 button, u32 state) {
@@ -8902,7 +9757,6 @@ static void RGFW_wl_keyboard_enter(void* data, struct wl_keyboard *keyboard, u32
RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface);
RGFW->kbOwner = win;
-
// this is to prevent race conditions
if (RGFW->data_device != NULL && win->src.data_source != NULL) {
wl_data_device_set_selection(RGFW->data_device, win->src.data_source, serial);
@@ -9136,7 +9990,7 @@ static void RGFW_wl_output_handle_done(void* data, struct wl_output* output) {
return;
}
- ((RGFW_monitorNode*)data)->disconnected = RGFW_TRUE;
+ ((RGFW_monitorNode*)data)->disconnected = RGFW_FALSE;
RGFW_monitorCallback(_RGFW->root, monitor, RGFW_TRUE);
}
@@ -9150,7 +10004,7 @@ static void RGFW_wl_create_outputs(struct wl_registry *const registry, u32 id) {
char RGFW_mon_default_name[10];
- RGFW_SNPRINTF(RGFW_mon_default_name, sizeof(RGFW_mon_default_name), "monitor-%li", _RGFW->monitors.count);
+ RGFW_SNPRINTF(RGFW_mon_default_name, sizeof(RGFW_mon_default_name), "monitor-%zu", _RGFW->monitors.count);
RGFW_STRNCPY(mon.name, RGFW_mon_default_name, sizeof(mon.name) - 1);
mon.name[sizeof(mon.name) - 1] = '\0';
@@ -9212,7 +10066,11 @@ static void RGFW_wl_data_source_send(void *data, struct wl_data_source *wl_data_
// a client can accept our clipboard
if (RGFW_STRNCMP(mime_type, "text/plain;charset=utf-8", 25) == 0) {
// do not write \0
- write(fd, _RGFW->clipboard, _RGFW->clipboard_len - 1);
+ size_t length = _RGFW->unixClipboard->length;
+ if (_RGFW->unixClipboard->data[0] == '\0') {
+ length -= 1;
+ }
+ write(fd, _RGFW->unixClipboard->data, length);
}
close(fd);
@@ -9222,7 +10080,7 @@ static void RGFW_wl_data_source_cancelled(void *data, struct wl_data_source *wl_
RGFW_info* RGFW = (RGFW_info*)data;
- if (RGFW->kbOwner->src.data_source == wl_data_source) {
+ if (RGFW->kbOwner && RGFW->kbOwner->src.data_source == wl_data_source) {
RGFW->kbOwner->src.data_source = NULL;
}
@@ -9251,7 +10109,7 @@ static void RGFW_wl_data_device_selection(void *data, struct wl_data_device *wl_
int pfds[2];
pipe(pfds);
- wl_data_offer_receive(wl_data_offer, "text/plain;charset=utf-8", pfds[1]);
+ wl_data_offer_receive(wl_data_offer, "text/plain", pfds[1]);
close(pfds[1]);
wl_display_roundtrip(_RGFW->wl_display);
@@ -9259,12 +10117,27 @@ static void RGFW_wl_data_device_selection(void *data, struct wl_data_device *wl_
char buf[1024];
ssize_t n = read(pfds[0], buf, sizeof(buf));
+ if (n <= 0) {
+ close(pfds[0]);
+ wl_data_offer_destroy(wl_data_offer);
+ return;
+ }
+
+ size_t length = (size_t)n;
+ if (buf[n - 1] != '\0') length += 1;
+
+ if (_RGFW->unixClipboard != NULL) RGFW_FREE(_RGFW->unixClipboard);
- _RGFW->clipboard = (char*)RGFW_ALLOC((size_t)n);
- RGFW_ASSERT(_RGFW->clipboard != NULL);
- RGFW_STRNCPY(_RGFW->clipboard, buf, (size_t)n);
+ _RGFW->unixClipboard = (RGFW_dataTransfer*)RGFW_ALLOC(sizeof(RGFW_dataTransfer) + (size_t)n);
+ RGFW_ASSERT(_RGFW->unixClipboard != NULL);
- _RGFW->clipboard_len = (size_t)n + 1;
+ char* data_ptr = &((char*)(void*)_RGFW->unixClipboard)[sizeof(RGFW_dataTransfer) - 1];
+ RGFW_MEMCPY(data_ptr, buf, (size_t)n);
+ data_ptr[length - 1] = '\0';
+
+ _RGFW->unixClipboard->data = data_ptr;
+ _RGFW->unixClipboard->type = RGFW_dataText;
+ _RGFW->unixClipboard->length = length;
close(pfds[0]);
@@ -9328,19 +10201,6 @@ static void RGFW_wl_global_registry_remove(void* data, struct wl_registry *regis
node = prev;
}
- if (node->output) {
- wl_output_destroy(node->output);
- }
-
- if (node->xdg_output) {
- zxdg_output_v1_destroy(node->xdg_output);
- }
-
- if (node->modeCount) {
- RGFW_FREE(node->modes);
- node->modeCount = 0;
- }
-
RGFW_monitorCallback(_RGFW->root, &node->mon, RGFW_FALSE);
RGFW_monitors_remove(node, prev);
}
@@ -9390,7 +10250,8 @@ static int RGFW_wl_create_shm_file(off_t size) {
return fd;
}
-i32 RGFW_initPlatform_Wayland(void) {
+i32 RGFW_initPlatform_Wayland(const char* className, RGFW_initFlags flags) {
+ RGFW_UNUSED(className); RGFW_UNUSED(flags);
_RGFW->wl_display = wl_display_connect(NULL);
if (_RGFW->wl_display == NULL) {
RGFW_debugCallback(RGFW_typeError, RGFW_errWayland, "Failed to load Wayland display");
@@ -9410,7 +10271,7 @@ i32 RGFW_initPlatform_Wayland(void) {
if (_RGFW->compositor == NULL) {
RGFW_debugCallback(RGFW_typeError, RGFW_errWayland, "Can't find compositor.");
- return 1;
+ return -1;
}
if (_RGFW->wl_cursor_theme == NULL) {
@@ -9447,9 +10308,9 @@ i32 RGFW_initPlatform_Wayland(void) {
}
void RGFW_deinitPlatform_Wayland(void) {
- if (_RGFW->clipboard) {
- RGFW_FREE(_RGFW->clipboard);
- _RGFW->clipboard = NULL;
+ if (_RGFW->unixClipboard) {
+ RGFW_FREE(_RGFW->unixClipboard);
+ _RGFW->unixClipboard = NULL;
}
if (_RGFW->wl_pointer) {
@@ -9459,7 +10320,10 @@ void RGFW_deinitPlatform_Wayland(void) {
wl_keyboard_destroy(_RGFW->wl_keyboard);
}
- wl_registry_destroy(_RGFW->registry);
+ if (_RGFW->registry) {
+ wl_registry_destroy(_RGFW->registry);
+ }
+
if (_RGFW->decoration_manager != NULL)
zxdg_decoration_manager_v1_destroy(_RGFW->decoration_manager);
if (_RGFW->relative_pointer_manager != NULL) {
@@ -9474,7 +10338,6 @@ void RGFW_deinitPlatform_Wayland(void) {
zwp_pointer_constraints_v1_destroy(_RGFW->constraint_manager);
}
- if (_RGFW->xdg_output_manager != NULL)
if (_RGFW->icon_manager != NULL) {
xdg_toplevel_icon_manager_v1_destroy(_RGFW->icon_manager);
}
@@ -9499,30 +10362,27 @@ void RGFW_deinitPlatform_Wayland(void) {
wp_pointer_warp_v1_destroy(_RGFW->wp_pointer_warp);
}
- RGFW_freeMouse(_RGFW->hiddenMouse);
+ if (_RGFW->hiddenMouse) {
+ RGFW_freeMouse(_RGFW->hiddenMouse);
+ }
- RGFW_monitorNode* node = _RGFW->monitors.list.head;
+ if (_RGFW->cursor_surface)
+ wl_surface_destroy(_RGFW->cursor_surface);
- while (node != NULL) {
- if (node->output) {
- wl_output_destroy(node->output);
- }
+ if (_RGFW->shm)
+ wl_shm_destroy(_RGFW->shm);
- if (node->xdg_output) {
- zxdg_output_v1_destroy(node->xdg_output);
- }
+ if (_RGFW->seat)
+ wl_seat_release(_RGFW->seat);
- _RGFW->monitors.count -= 1;
- node = node->next;
+ if (_RGFW->xdg_wm_base)
+ xdg_wm_base_destroy(_RGFW->xdg_wm_base);
- }
+ if (_RGFW->compositor)
+ wl_compositor_destroy(_RGFW->compositor);
- wl_surface_destroy(_RGFW->cursor_surface);
- wl_shm_destroy(_RGFW->shm);
- wl_seat_release(_RGFW->seat);
- xdg_wm_base_destroy(_RGFW->xdg_wm_base);
- wl_compositor_destroy(_RGFW->compositor);
- wl_display_disconnect(_RGFW->wl_display);
+ if (_RGFW->wl_display)
+ wl_display_disconnect(_RGFW->wl_display);
}
RGFW_format RGFW_FUNC(RGFW_nativeFormat)(void) { return RGFW_formatBGRA8; }
@@ -9661,9 +10521,6 @@ RGFW_window* RGFW_FUNC(RGFW_createWindowPlatform) (const char* name, RGFW_window
win->src.xdg_toplevel = xdg_surface_get_toplevel(win->src.xdg_surface);
- if (_RGFW->className == NULL)
- _RGFW->className = (char*)name;
-
xdg_toplevel_set_app_id(win->src.xdg_toplevel, name);
xdg_surface_set_window_geometry(win->src.xdg_surface, 0, 0, win->w, win->h);
@@ -9746,21 +10603,25 @@ RGFW_window* RGFW_FUNC(RGFW_createWindowPlatform) (const char* name, RGFW_window
}
RGFW_bool RGFW_FUNC(RGFW_getGlobalMouse) (i32* x, i32* y) {
- RGFW_init();
+ RGFW_ASSERT(_RGFW && "An RGFW context must be initialized using RGFW_init and/or set with RGFW_setInfo");
if (x) *x = 0;
if (y) *y = 0;
return RGFW_FALSE;
}
RGFW_key RGFW_FUNC(RGFW_physicalToMappedKey)(RGFW_key key) {
- u32 keycode = RGFW_rgfwToApiKey(key);
- xkb_keycode_t kc = keycode + 8;
- xkb_keysym_t sym = xkb_state_key_get_one_sym(_RGFW->xkb_state, kc);
+ xkb_keycode_t keycode = (xkb_keycode_t)RGFW_rgfwToApiKey(key);
+ xkb_keysym_t sym = xkb_state_key_get_one_sym(_RGFW->xkb_state, keycode);
if (sym < 256) {
return (RGFW_key)sym;
}
switch (sym) {
+ case XKB_KEY_BackSpace: return RGFW_keyBackSpace;
+ case XKB_KEY_Tab: return RGFW_keyTab;
+ case XKB_KEY_Return: return RGFW_keyReturn;
+ case XKB_KEY_Escape: return RGFW_keyEscape;
+ case XKB_KEY_Delete: return RGFW_keyDelete;
case XKB_KEY_F1: return RGFW_keyF1;
case XKB_KEY_F2: return RGFW_keyF2;
case XKB_KEY_F3: return RGFW_keyF3;
@@ -9852,7 +10713,7 @@ void RGFW_FUNC(RGFW_pollEvents) (void) {
}
}
if (_RGFW->wl_repeat_info_rate != 0 && _RGFW->last_key) {
- u32 now = (u32)(RGFW_linux_getTimeNS() / 1000000);
+ u32 now = (u32)(RGFW_unix_getTimeNS() / 1000000);
if (now > _RGFW->last_key_time) {
RGFW_wl_send_key_event(_RGFW->last_key);
_RGFW->last_key_time = now + 1000 / (u32)_RGFW->wl_repeat_info_rate;
@@ -9861,25 +10722,41 @@ void RGFW_FUNC(RGFW_pollEvents) (void) {
/* read the events; if empty this reads from the */
/* wayland file descriptor */
- if (wl_display_dispatch(_RGFW->wl_display) == -1) {
- return;
- }
+ struct pollfd fds;
+ memset(&fds, 0, sizeof(fds));
+ fds.fd = wl_display_get_fd(_RGFW->wl_display);
+ fds.events = POLLIN;
+ fds.revents = 0;
-}
+ while (1) {
+ while (wl_display_prepare_read(_RGFW->wl_display) != 0) {
+ if (wl_display_dispatch_pending(_RGFW->wl_display) > 0)
+ return;
+ }
-void RGFW_FUNC(RGFW_window_move) (RGFW_window* win, i32 x, i32 y) {
- RGFW_ASSERT(win != NULL);
- win->x = x;
- win->y = y;
+ if (poll(&fds, 1, 0) == 0) {
+ wl_display_cancel_read(_RGFW->wl_display);
+ return;
+ }
+
+ if (fds.revents & POLLIN) {
+ wl_display_read_events(_RGFW->wl_display);
+ if (wl_display_dispatch_pending(_RGFW->wl_display) > 0) {
+ return;
+ }
+ } else {
+ wl_display_cancel_read(_RGFW->wl_display);
+ }
+ }
}
+void RGFW_FUNC(RGFW_window_movePlatform) (RGFW_window* win, i32 x, i32 y) {
+ RGFW_UNUSED(win); RGFW_UNUSED(x); RGFW_UNUSED(y);
+}
-void RGFW_FUNC(RGFW_window_resize) (RGFW_window* win, i32 w, i32 h) {
- RGFW_ASSERT(win != NULL);
- win->w = w;
- win->h = h;
+void RGFW_FUNC(RGFW_window_resizePlatform) (RGFW_window* win, i32 w, i32 h) {
if (_RGFW->compositor) {
- xdg_surface_set_window_geometry(win->src.xdg_surface, 0, 0, win->w, win->h);
+ xdg_surface_set_window_geometry(win->src.xdg_surface, 0, 0, w, h);
#ifdef RGFW_OPENGL
if (win->src.ctx.egl)
wl_egl_window_resize(win->src.ctx.egl->eglWindow, (i32)w, (i32)h, 0, 0);
@@ -9914,13 +10791,8 @@ void RGFW_toggleWaylandMaximized(RGFW_window* win, RGFW_bool maximized) {
}
}
-void RGFW_FUNC(RGFW_window_maximize) (RGFW_window* win) {
- win->internal.oldX = win->x;
- win->internal.oldY = win->y;
- win->internal.oldW = win->w;
- win->internal.oldH = win->h;
+void RGFW_FUNC(RGFW_window_maximizePlatform) (RGFW_window* win) {
RGFW_toggleWaylandMaximized(win, 1);
- RGFW_window_fetchSize(win, NULL, NULL);
return;
}
@@ -9932,21 +10804,12 @@ void RGFW_FUNC(RGFW_window_raise)(RGFW_window* win) {
RGFW_ASSERT(win);
}
-void RGFW_FUNC(RGFW_window_setFullscreen)(RGFW_window* win, RGFW_bool fullscreen) {
- RGFW_ASSERT(win != NULL);
+void RGFW_FUNC(RGFW_window_setFullscreenPlatform)(RGFW_window* win, RGFW_bool fullscreen) {
if (fullscreen) {
-
- win->internal.flags |= RGFW_windowFullscreen;
- win->internal.oldX = win->x;
- win->internal.oldY = win->y;
- win->internal.oldW = win->w;
- win->internal.oldH = win->h;
xdg_toplevel_set_fullscreen(win->src.xdg_toplevel, NULL); /* let the compositor decide */
} else {
- win->internal.flags &= ~(u32)RGFW_windowFullscreen;
xdg_toplevel_unset_fullscreen(win->src.xdg_toplevel);
}
-
}
void RGFW_FUNC(RGFW_window_setFloating) (RGFW_window* win, RGFW_bool floating) {
@@ -9959,7 +10822,7 @@ void RGFW_FUNC(RGFW_window_setOpacity) (RGFW_window* win, u8 opacity) {
RGFW_UNUSED(opacity);
}
-void RGFW_FUNC(RGFW_window_minimize)(RGFW_window* win) {
+void RGFW_FUNC(RGFW_window_minimizePlatform)(RGFW_window* win) {
RGFW_ASSERT(win != NULL);
if (RGFW_window_isMaximized(win)) return;
win->internal.oldX = win->x;
@@ -9970,18 +10833,9 @@ void RGFW_FUNC(RGFW_window_minimize)(RGFW_window* win) {
xdg_toplevel_set_minimized(win->src.xdg_toplevel);
}
-void RGFW_FUNC(RGFW_window_restore)(RGFW_window* win) {
+void RGFW_FUNC(RGFW_window_restorePlatform)(RGFW_window* win) {
RGFW_ASSERT(win != NULL);
RGFW_toggleWaylandMaximized(win, RGFW_FALSE);
-
- RGFW_window_move(win, win->internal.oldX, win->internal.oldY);
- RGFW_window_resize(win, win->internal.oldW, win->internal.oldH);
-
- RGFW_window_show(win);
- RGFW_window_move(win, win->internal.oldX, win->internal.oldY);
- RGFW_window_resize(win, win->internal.oldW, win->internal.oldH);
-
- RGFW_window_show(win);
}
RGFW_bool RGFW_FUNC(RGFW_window_isFloating)(RGFW_window* win) {
@@ -10118,9 +10972,8 @@ void RGFW_FUNC(RGFW_window_hide) (RGFW_window* win) {
win->internal.flags |= RGFW_windowHide;
}
-void RGFW_FUNC(RGFW_window_show) (RGFW_window* win) {
+void RGFW_FUNC(RGFW_window_showPlatform) (RGFW_window* win) {
win->internal.flags &= ~(u32)RGFW_windowHide;
- if (win->internal.flags & RGFW_windowFocusOnShow) RGFW_window_focus(win);
/* wl_surface_attach(win->src.surface, win->x, win->y, win->w, win->h, 0, 0); */
wl_surface_commit(win->src.surface);
}
@@ -10131,31 +10984,57 @@ void RGFW_FUNC(RGFW_window_flash) (RGFW_window* win, RGFW_flashRequest request)
}
}
-RGFW_ssize_t RGFW_FUNC(RGFW_readClipboardPtr) (char* str, size_t strCapacity) {
+RGFW_bool RGFW_FUNC(RGFW_readClipboardPtr) (RGFW_dataTransferType requestedType, u8* buffer, size_t capacity, RGFW_dataTransfer* data) {
+ RGFW_ASSERT(data != NULL);
+
+ if (requestedType != RGFW_dataText) return RGFW_FALSE;
+
+ if (_RGFW->unixClipboard == NULL || _RGFW->unixClipboard->length == 0) {
+ data->length = 0;
+ data->type = RGFW_dataNone;
+ return RGFW_FALSE;
+ }
+
+ data->length = _RGFW->unixClipboard->length;
+ data->type = RGFW_dataText;
+
+ if (buffer == NULL) return RGFW_TRUE;
- RGFW_UNUSED(strCapacity);
+ if (_RGFW->unixClipboard->length > capacity) return RGFW_FALSE;
- if (str != NULL)
- RGFW_STRNCPY(str, _RGFW->clipboard, _RGFW->clipboard_len - 1);
- _RGFW->clipboard[_RGFW->clipboard_len - 1] = '\0';
- return (RGFW_ssize_t)_RGFW->clipboard_len - 1;
+ RGFW_MEMCPY(buffer, _RGFW->unixClipboard->data, _RGFW->unixClipboard->length);
+ data->data = (const char*)buffer;
+
+ return RGFW_TRUE;
}
-void RGFW_FUNC(RGFW_writeClipboard) (const char* text, u32 textLen) {
+RGFW_bool RGFW_FUNC(RGFW_writeClipboard) (const RGFW_dataTransfer* data) {
+ RGFW_ASSERT(data != NULL);
- // compositor does not support wl_data_device_manager
- // clients cannot read rgfw's clipboard
- if (_RGFW->data_device_manager == NULL) return;
+ /* compositor does not support wl_data_device_manager
+ clients cannot read rgfw's clipboard
+ */
+ if (_RGFW->data_device_manager == NULL) return RGFW_FALSE;
// clear the clipboard
- if (_RGFW->clipboard)
- RGFW_FREE(_RGFW->clipboard);
+ if (_RGFW->unixClipboard) {
+ RGFW_FREE(_RGFW->unixClipboard);
+ _RGFW->unixClipboard = NULL;
+ }
// set the contents
- _RGFW->clipboard = (char*)RGFW_ALLOC(textLen);
- RGFW_ASSERT(_RGFW->clipboard != NULL);
- RGFW_STRNCPY(_RGFW->clipboard, text, textLen - 1);
- _RGFW->clipboard[textLen - 1] = '\0';
- _RGFW->clipboard_len = textLen;
+ _RGFW->unixClipboard = (RGFW_dataTransfer*)RGFW_ALLOC(sizeof(RGFW_dataTransfer) + data->length);
+ RGFW_ASSERT(_RGFW->unixClipboard!= NULL);
+
+ size_t length = data->length;
+ if (data->data[length - 1] != '\0') length += 1;
+
+ char* data_ptr = &((char*)(void*)_RGFW->unixClipboard)[sizeof(RGFW_dataTransfer) - 1];
+ RGFW_MEMCPY(data_ptr, data->data, data->length);
+ data_ptr[length - 1] = '\0';
+
+ _RGFW->unixClipboard->data = data_ptr;
+ _RGFW->unixClipboard->type = RGFW_dataText;
+ _RGFW->unixClipboard->length = length;
// means we already wrote to the clipboard
// so destroy it to create a new one
@@ -10172,9 +11051,8 @@ void RGFW_FUNC(RGFW_writeClipboard) (const char* text, u32 textLen) {
// basic error checking
if (win->src.data_source == NULL) {
RGFW_debugCallback(RGFW_typeError, RGFW_errClipboard, "Could not create clipboard data source");
- return;
+ return RGFW_FALSE;
}
- wl_data_source_offer(win->src.data_source , "text/plain;charset=utf-8");
// needed RGFW_doNothing because wayland will call the functions
// if not set they are random data that lead to a crash
@@ -10188,7 +11066,9 @@ void RGFW_FUNC(RGFW_writeClipboard) (const char* text, u32 textLen) {
};
wl_data_source_add_listener(win->src.data_source, &data_source_listener, _RGFW);
+ wl_data_source_offer(win->src.data_source , "text/plain;charset=utf-8");
+ return RGFW_TRUE;
}
RGFW_bool RGFW_FUNC(RGFW_window_isHidden) (RGFW_window* win) {
@@ -10210,8 +11090,25 @@ void RGFW_FUNC(RGFW_pollMonitors) (void) {
_RGFW->monitors.primary = _RGFW->monitors.list.head;
}
+void RGFW_FUNC(RGFW_monitorNode_free) (RGFW_monitorNode* node) {
+ RGFW_ASSERT(node);
+
+ if (node->output) {
+ wl_output_destroy(node->output);
+ }
+
+ if (node->xdg_output) {
+ zxdg_output_v1_destroy(node->xdg_output);
+ }
+
+ if (node->modes) {
+ RGFW_FREE(node->modes);
+ node->modeCount = 0;
+ }
+}
RGFW_bool RGFW_FUNC(RGFW_monitor_getWorkarea) (RGFW_monitor* monitor, i32* x, i32* y, i32* width, i32* height) {
+ RGFW_ASSERT(monitor != NULL);
/* NOTE: Wayland has no way to get the actual workarea as far as I'm aware :( */
if (x) *x = monitor->x;
if (y) *y = monitor->y;
@@ -10221,6 +11118,7 @@ RGFW_bool RGFW_FUNC(RGFW_monitor_getWorkarea) (RGFW_monitor* monitor, i32* x, i3
}
size_t RGFW_FUNC(RGFW_monitor_getModesPtr) (RGFW_monitor* monitor, RGFW_monitorMode** modes) {
+ RGFW_ASSERT(monitor != NULL);
if (modes) {
RGFW_MEMCPY((*modes), monitor->node->modes, monitor->node->modeCount * sizeof(RGFW_monitorMode));
}
@@ -10229,16 +11127,19 @@ size_t RGFW_FUNC(RGFW_monitor_getModesPtr) (RGFW_monitor* monitor, RGFW_monitorM
}
size_t RGFW_FUNC(RGFW_monitor_getGammaRampPtr) (RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
+ RGFW_ASSERT(monitor != NULL);
RGFW_UNUSED(monitor); RGFW_UNUSED(ramp);
return 0;
}
RGFW_bool RGFW_FUNC(RGFW_monitor_setGammaRamp) (RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
+ RGFW_ASSERT(monitor != NULL);
RGFW_UNUSED(monitor); RGFW_UNUSED(ramp);
return RGFW_FALSE;
}
RGFW_bool RGFW_FUNC(RGFW_monitor_requestMode) (RGFW_monitor* mon, RGFW_monitorMode* mode, RGFW_modeRequest request) {
+ RGFW_ASSERT(mon != NULL);
for (size_t i = 0; i < mon->node->modeCount; i++) {
if (RGFW_monitorModeCompare(mode, &mon->node->modes[i], request) == RGFW_FALSE) {
continue;
@@ -10252,7 +11153,8 @@ RGFW_bool RGFW_FUNC(RGFW_monitor_requestMode) (RGFW_monitor* mon, RGFW_monitorMo
}
RGFW_bool RGFW_FUNC(RGFW_monitor_setMode) (RGFW_monitor* mon, RGFW_monitorMode* mode) {
- RGFW_UNUSED(mon); RGFW_UNUSED(mode);
+ RGFW_ASSERT(mon != NULL);
+ mon->mode = *mode;
return RGFW_FALSE;
}
@@ -10271,17 +11173,31 @@ RGFW_bool RGFW_FUNC(RGFW_extensionSupportedPlatform_OpenGL) (const char * extens
RGFW_proc RGFW_FUNC(RGFW_getProcAddress_OpenGL) (const char* procname) { return RGFW_getProcAddress_EGL(procname); }
-RGFW_bool RGFW_FUNC(RGFW_window_createContextPtr_OpenGL)(RGFW_window* win, RGFW_glContext* ctx, RGFW_glHints* hints) {
- RGFW_bool out = RGFW_window_createContextPtr_EGL(win, &ctx->egl, hints);
+RGFW_bool RGFW_FUNC(RGFW_createContextPtr_OpenGL)(RGFW_glContext* ctx, RGFW_glHints* hints) {
+ RGFW_bool out = RGFW_createContextPtr_EGL(&ctx->egl, hints);
+ return out;
+}
+void RGFW_FUNC(RGFW_deleteContextPtr_OpenGL) (RGFW_glContext* ctx) { RGFW_deleteContextPtr_EGL(&ctx->egl); }
+RGFW_bool RGFW_FUNC(RGFW_window_setContext_OpenGL) (RGFW_window* win, RGFW_glContext* context) {
+ RGFW_ASSERT(win);
+ if (context == NULL && win->src.ctx.native != NULL) {
+ RGFW_window_setContext_EGL(win, 0);
+ win->src.ctx.native = NULL;
+ RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL window surface freed");
+ return RGFW_TRUE;
+ }
+
+ win->src.ctx.native = context;
win->src.gfxType = RGFW_gfxNativeOpenGL;
+ if (RGFW_window_setContext_EGL(win, &context->egl) == RGFW_FALSE) return RGFW_FALSE;
RGFW_window_swapInterval_OpenGL(win, 0);
- return out;
+ return RGFW_TRUE;
}
-void RGFW_FUNC(RGFW_window_deleteContextPtr_OpenGL) (RGFW_window* win, RGFW_glContext* ctx) { RGFW_window_deleteContextPtr_EGL(win, &ctx->egl); win->src.ctx.native = NULL; }
void RGFW_FUNC(RGFW_window_makeCurrentContext_OpenGL) (RGFW_window* win) { RGFW_window_makeCurrentContext_EGL(win); }
void* RGFW_FUNC(RGFW_getCurrentContext_OpenGL) (void) { return RGFW_getCurrentContext_EGL(); }
+void* RGFW_FUNC(RGFW_getCurrentSurface_OpenGL) (void) { return RGFW_getCurrentSurface_EGL(); }
void RGFW_FUNC(RGFW_window_swapBuffers_OpenGL) (RGFW_window* win) { RGFW_window_swapBuffers_EGL(win); }
void RGFW_FUNC(RGFW_window_swapInterval_OpenGL) (RGFW_window* win, i32 swapInterval) { RGFW_window_swapInterval_EGL(win, swapInterval); }
#endif /* RGFW_OPENGL */
@@ -10344,16 +11260,6 @@ WGPUSurface RGFW_FUNC(RGFW_window_createSurface_WebGPU) (RGFW_window* window, WG
*/
#ifdef RGFW_WINDOWS
-#ifndef WIN32_LEAN_AND_MEAN
- #define WIN32_LEAN_AND_MEAN
-#endif
-
-#ifndef OEMRESOURCE
- #define OEMRESOURCE
-#endif
-
-#include <windows.h>
-
#ifndef OCR_NORMAL
#define OCR_NORMAL 32512
#define OCR_IBEAM 32513
@@ -10381,12 +11287,17 @@ WGPUSurface RGFW_FUNC(RGFW_window_createSurface_WebGPU) (RGFW_window* window, WG
#define WM_DPICHANGED 0x02E0
#endif
+#define RGFW_LOAD_LIBRARY(x, lib) if (x == NULL) { x = LoadLibraryA(lib); RGFW_ASSERT(x != NULL); }
+#define RGFW_PROC_DEF(proc, name) if (name##SRC == NULL && proc != NULL) { \
+ name##SRC = (PFN_##name)(RGFW_proc)GetProcAddress((proc), (#name)); \
+ RGFW_ASSERT(name##SRC != NULL); \
+ }
RGFWDEF DWORD RGFW_winapi_window_getStyle(RGFW_window* win, RGFW_windowFlags flags);
DWORD RGFW_winapi_window_getStyle(RGFW_window* win, RGFW_windowFlags flags) {
RGFW_UNUSED(win);
DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
- if ((flags & RGFW_windowFullscreen)) {
+ if ((flags & RGFW_windowFullscreenExclusive)) {
style |= WS_POPUP;
} else {
style |= WS_SYSMENU | WS_MINIMIZEBOX;
@@ -10407,68 +11318,155 @@ DWORD RGFW_winapi_window_getStyle(RGFW_window* win, RGFW_windowFlags flags) {
RGFWDEF DWORD RGFW_winapi_window_getExStyle(RGFW_window* win, RGFW_windowFlags flags);
DWORD RGFW_winapi_window_getExStyle(RGFW_window* win, RGFW_windowFlags flags) {
DWORD style = WS_EX_APPWINDOW;
- if (flags & RGFW_windowFullscreen || (flags & RGFW_windowFloating || RGFW_window_isFloating(win))) {
+ if (flags & RGFW_windowFullscreenExclusive || (flags & RGFW_windowFloating || RGFW_window_isFloating(win))) {
style |= WS_EX_TOPMOST;
}
return style;
}
-RGFW_bool RGFW_createUTF8FromWideStringWin32(const WCHAR* source, char* out, size_t max);
+RGFWDEF i32 RGFW_createUTF8FromWideStringWin32(const WCHAR* source, char* out, size_t max);
+i32 RGFW_createUTF8FromWideStringWin32(const WCHAR* source, char* output, size_t max) {
+ RGFW_ASSERT(source != NULL);
-#define GL_FRONT 0x0404
-#define GL_BACK 0x0405
-#define GL_LEFT 0x0406
-#define GL_RIGHT 0x0407
+ i32 size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
+ if (!size) {
+ return RGFW_FALSE;
+ }
-typedef int (*PFN_wglGetSwapIntervalEXT)(void);
-PFN_wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc = NULL;
-#define wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc
+ if (output == NULL || max == 0) {
+ return size;
+ }
-/* these two wgl functions need to be preloaded */
-typedef HGLRC (WINAPI *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hdc, HGLRC hglrc, const int *attribList);
-PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
+ if ((size_t)size > max)
+ size = (i32)max;
-HMODULE RGFW_wgl_dll = NULL;
+ if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, output, size, NULL, NULL)) {
+ return RGFW_FALSE;
+ }
-#ifndef RGFW_NO_LOAD_WGL
- typedef HGLRC(WINAPI* PFN_wglCreateContext)(HDC);
- typedef BOOL(WINAPI* PFN_wglDeleteContext)(HGLRC);
- typedef PROC(WINAPI* PFN_wglGetProcAddress)(LPCSTR);
- typedef BOOL(WINAPI* PFN_wglMakeCurrent)(HDC, HGLRC);
- typedef HDC(WINAPI* PFN_wglGetCurrentDC)(void);
- typedef HGLRC(WINAPI* PFN_wglGetCurrentContext)(void);
- typedef BOOL(WINAPI* PFN_wglShareLists)(HGLRC, HGLRC);
+ return size;
+}
- PFN_wglCreateContext wglCreateContextSRC;
- PFN_wglDeleteContext wglDeleteContextSRC;
- PFN_wglGetProcAddress wglGetProcAddressSRC;
- PFN_wglMakeCurrent wglMakeCurrentSRC;
- PFN_wglGetCurrentDC wglGetCurrentDCSRC;
- PFN_wglGetCurrentContext wglGetCurrentContextSRC;
- PFN_wglShareLists wglShareListsSRC;
+#ifdef RGFW_OPENGL
+#define WGL_ACCELERATION_ARB 0x2003
+#define WGL_FULL_ACCELERATION_ARB 0x2027
+#define WGL_DRAW_TO_WINDOW_ARB 0x2001
+#define WGL_PIXEL_TYPE_ARB 0x2013
+#define WGL_TYPE_RGBA_ARB 0x202b
+#define WGL_SUPPORT_OPENGL_ARB 0x2010
+#define WGL_COLOR_BITS_ARB 0x2014
+#define WGL_DOUBLE_BUFFER_ARB 0x2011
+#define WGL_ALPHA_BITS_ARB 0x201b
+#define WGL_DEPTH_BITS_ARB 0x2022
+#define WGL_STENCIL_BITS_ARB 0x2023
+#define WGL_STEREO_ARB 0x2012
+#define WGL_AUX_BUFFERS_ARB 0x2024
+#define WGL_RED_BITS_ARB 0x2015
+#define WGL_GREEN_BITS_ARB 0x2017
+#define WGL_BLUE_BITS_ARB 0x2019
+#define WGL_ACCUM_RED_BITS_ARB 0x201e
+#define WGL_ACCUM_GREEN_BITS_ARB 0x201f
+#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
+#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
+#define WGL_COLORSPACE_SRGB_EXT 0x3089
+#define WGL_SAMPLE_BUFFERS_ARB 0x2041
+#define WGL_SAMPLES_ARB 0x2042
+#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0x0000
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
+#define WGL_CONTEXT_FLAGS_ARB 0x2094
+#define WGL_ACCESS_READ_WRITE_NV 0x00000001
+#define WGL_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004
+#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
+#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
+#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
+#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001
+#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
- #define wglCreateContext wglCreateContextSRC
- #define wglDeleteContext wglDeleteContextSRC
- #define wglGetProcAddress wglGetProcAddressSRC
- #define wglMakeCurrent wglMakeCurrentSRC
- #define wglGetCurrentDC wglGetCurrentDCSRC
- #define wglGetCurrentContext wglGetCurrentContextSRC
- #define wglShareLists wglShareListsSRC
-#endif
+typedef int (*RGFW_wglGetSwapIntervalEXTProc)(void);
+typedef HGLRC (WINAPI *RGFW_wglCreateContextAttribsARBProc)(HDC hdc, HGLRC hglrc, const int *attribList);
+typedef HGLRC(WINAPI* RGFW_wglCreateContextProc)(HDC);
+typedef BOOL(WINAPI* RGFW_wglDeleteContextProc)(HGLRC);
+typedef PROC(WINAPI* RGFW_wglGetProcAddressProc)(LPCSTR);
+typedef BOOL(WINAPI* RGFW_wglMakeCurrentProc)(HDC, HGLRC);
+typedef HGLRC(WINAPI* RGFW_wglGetCurrentContextProc)(void);
+typedef HDC(WINAPI* RGFW_wglGetCurrentDCProc)(void);
+typedef BOOL(WINAPI* RGFW_wglShareListsProc)(HGLRC, HGLRC);
+typedef HRESULT (APIENTRY* RGFW_wglChoosePixelFormatARBProc)(HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats);
+typedef BOOL(APIENTRY* RGFW_wglSwapIntervalEXTProc)(int interval);
-void* RGFW_window_getHWND(RGFW_window* win) { return win->src.window; }
-void* RGFW_window_getHDC(RGFW_window* win) { return win->src.hdc; }
+RGFW_wglCreateContextProc RGFW_wglCreateContext;
+RGFW_wglDeleteContextProc RGFW_wglDeleteContext;
+RGFW_wglMakeCurrentProc RGFW_wglMakeCurrent;
+RGFW_wglGetCurrentDCProc RGFW_wglGetCurrentDC;
+RGFW_wglGetCurrentContextProc RGFW_wglGetCurrentContext;
+RGFW_wglShareListsProc RGFW_wglShareLists;
+RGFW_wglCreateContextAttribsARBProc RGFW_wglCreateContextAttribsARB;
+RGFW_wglGetSwapIntervalEXTProc RGFW_wglGetSwapIntervalEXT;
+RGFW_wglChoosePixelFormatARBProc RGFW_wglChoosePixelFormatARB;
+RGFW_wglSwapIntervalEXTProc RGFW_wglSwapIntervalEXT;
-#ifdef RGFW_OPENGL
-RGFWDEF void RGFW_win32_loadOpenGLFuncs(HWND dummyWin);
+RGFW_bool RGFW_loadGL(void) {
+ RGFW_ASSERT(_RGFW && "An RGFW context must be initialized using RGFW_init and/or set with RGFW_setInfo");
+ if (_RGFW->nativeGL_handle && _RGFW->glGetProcAddress != NULL) {
+ return RGFW_TRUE;
+ }
+
+ RGFW_LOAD_LIBRARY(_RGFW->nativeGL_handle, "opengl32.dll");
+ _RGFW->glGetProcAddress = (RGFW_proc(*)(const char*))(RGFW_proc)GetProcAddress((HMODULE)_RGFW->nativeGL_handle, "wglGetProcAddress");
+ RGFW_ASSERT(_RGFW->glGetProcAddress);
+
+ #define RGFW_WGL_PROC(name) if (RGFW_##name == NULL) RGFW_##name = (RGFW_##name##Proc)RGFW_getProcAddress_OpenGL(#name);
+
+ RGFW_WGL_PROC(wglCreateContext);
+ RGFW_WGL_PROC(wglDeleteContext);
+ RGFW_WGL_PROC(wglMakeCurrent);
+ RGFW_WGL_PROC(wglGetCurrentDC);
+ RGFW_WGL_PROC(wglGetCurrentContext);
+ RGFW_WGL_PROC(wglShareLists);
+
+ HWND dummyWin = CreateWindowW(_RGFW->wndClass.lpszClassName, (wchar_t*)NULL, 0, 0, 0, 0, 0, 0, 0, _RGFW->instance, 0);
+ HDC dummy_dc = GetDC(dummyWin);
+ u32 pfd_flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
+
+ PIXELFORMATDESCRIPTOR pfd = {sizeof(pfd), 1, pfd_flags, PFD_TYPE_RGBA, 32, 8, PFD_MAIN_PLANE, 32, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 32, 8, 0, PFD_MAIN_PLANE, 0, 0, 0, 0};
+
+ int dummy_pixel_format = ChoosePixelFormat(dummy_dc, &pfd);
+ SetPixelFormat(dummy_dc, dummy_pixel_format, &pfd);
+
+ HGLRC dummy_context = RGFW_wglCreateContext(dummy_dc);
+
+ HGLRC cur = RGFW_wglGetCurrentContext();
+ RGFW_wglMakeCurrent(dummy_dc, dummy_context);
-typedef HRESULT (APIENTRY* PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats);
-PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL;
+ RGFW_WGL_PROC(wglCreateContextAttribsARB);
+ RGFW_WGL_PROC(wglChoosePixelFormatARB);
+ RGFW_WGL_PROC(wglSwapIntervalEXT);
+
+ #undef RGFW_WGL_PROC
+
+ if (RGFW_wglSwapIntervalEXT == NULL) {
+ RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to load swap interval function");
+ }
+
+ RGFW_wglMakeCurrent(dummy_dc, cur);
+ RGFW_wglDeleteContext(dummy_context);
+ ReleaseDC(dummyWin, dummy_dc);
+ DestroyWindow(dummyWin);
+
+ return RGFW_TRUE;
+}
-typedef BOOL(APIENTRY* PFNWGLSWAPINTERVALEXTPROC)(int interval);
-PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL;
#endif
+void* RGFW_window_getHWND(RGFW_window* win) { return win->src.window; }
+void* RGFW_window_getHDC(RGFW_window* win) { return win->src.hdc; }
#ifndef RGFW_NO_DWM
HMODULE RGFW_dwm_dll = NULL;
@@ -10525,6 +11523,15 @@ void RGFW_win32_makeWindowDarkMode(RGFW_window* win, RGFW_bool state) {
LRESULT CALLBACK WndProcW(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK WndProcW(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
+ switch (message) {
+ case WM_DISPLAYCHANGE:
+ RGFW_pollMonitors();
+ break;
+ default: break;
+ }
+
+ if (hWnd == _RGFW->helperWindow) return DefWindowProcW(hWnd, message, wParam, lParam);
+
RGFW_window* win = (RGFW_window*)GetPropW(hWnd, L"RGFW");
if (win == NULL) return DefWindowProcW(hWnd, message, wParam, lParam);
@@ -10538,11 +11545,7 @@ LRESULT CALLBACK WndProcW(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
AdjustWindowRectEx(&frame, style, FALSE, exStyle);
switch (message) {
- case WM_DISPLAYCHANGE:
- RGFW_pollMonitors();
- break;
case WM_CLOSE:
- case WM_QUIT:
RGFW_windowCloseCallback(win);
return 0;
case WM_ACTIVATE: {
@@ -10627,10 +11630,15 @@ LRESULT CALLBACK WndProcW(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
return DefWindowProcW(hWnd, message, wParam, lParam);
}
case WM_PAINT: {
- PAINTSTRUCT ps;
- BeginPaint(hWnd, &ps);
- RGFW_windowRefreshCallback(win, 0, 0, win->w, win->h);
- EndPaint(hWnd, &ps);
+ RECT rect;
+ if (GetUpdateRect(hWnd, &rect, FALSE)) {
+ RGFW_windowRefreshCallback(win, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+ } else {
+ PAINTSTRUCT ps;
+ BeginPaint(hWnd, &ps);
+ RGFW_windowRefreshCallback(win, 0, 0, win->w, win->h);
+ EndPaint(hWnd, &ps);
+ }
return DefWindowProcW(hWnd, message, wParam, lParam);
}
@@ -10767,7 +11775,7 @@ LRESULT CALLBACK WndProcW(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
RGFW_mouseNotifyCallback(win, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), RGFW_TRUE);
}
- RGFW_mousePosCallback(win, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ RGFW_mouseMotionCallback(win, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
}
case WM_INPUT: {
@@ -10819,6 +11827,7 @@ LRESULT CALLBACK WndProcW(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
else value = (message == WM_LBUTTONDOWN) ? (u8)RGFW_mouseLeft :
(message == WM_RBUTTONDOWN) ? (u8)RGFW_mouseRight : (u8)RGFW_mouseMiddle;
+ SetCapture(win->src.window);
RGFW_mouseButtonCallback(win, value, 1);
break;
}
@@ -10830,6 +11839,9 @@ LRESULT CALLBACK WndProcW(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
(message == WM_RBUTTONUP) ? (u8)RGFW_mouseRight : (u8)RGFW_mouseMiddle;
RGFW_mouseButtonCallback(win, value, 0);
+
+ RGFW_mouseButton i = 0;
+ for (i = RGFW_mouseLeft; i < RGFW_mouseFinal && RGFW_isMouseDown(i) == RGFW_FALSE; i += 1);
break;
}
case WM_MOUSEWHEEL: {
@@ -10855,20 +11867,23 @@ LRESULT CALLBACK WndProcW(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
u32 i;
for (i = 0; i < count; i++) {
- UINT length = DragQueryFileW(drop, i, NULL, 0);
- if (length == 0)
+ UINT length = DragQueryFileW(drop, i, NULL, 0) + 1;
+ if (length <= 1)
continue;
- WCHAR* buffer = (WCHAR*)RGFW_ALLOC(sizeof(WCHAR) * (length + 1));
- char* cbuffer = (char*)RGFW_ALLOC(length + 1);
-
- DragQueryFileW(drop, i, buffer, length + 1);
+ WCHAR* buffer = (WCHAR*)RGFW_ALLOC(sizeof(WCHAR) * length);
+ DragQueryFileW(drop, i, buffer, length);
- RGFW_createUTF8FromWideStringWin32(buffer, cbuffer, length);
+ i32 clength = RGFW_createUTF8FromWideStringWin32(buffer, NULL, 0);
+ if (clength > 0) {
+ char* cbuffer = (char*)RGFW_ALLOC((size_t)clength);
+ if (RGFW_createUTF8FromWideStringWin32(buffer, cbuffer, (size_t)clength) != RGFW_FALSE) {
+ RGFW_dataDropCallback(win, cbuffer, (size_t)clength, RGFW_dataFile);
+ }
+ RGFW_FREE(cbuffer);
+ }
- RGFW_dataDropCallback(win, cbuffer, length + 1, RGFW_dataFile);
RGFW_FREE(buffer);
- RGFW_FREE(cbuffer);
}
DragFinish(drop);
@@ -10899,10 +11914,6 @@ LRESULT CALLBACK WndProcW(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
__declspec(dllimport) u32 __stdcall timeBeginPeriod(u32 uPeriod);
__declspec(dllimport) u32 __stdcall timeEndPeriod(u32 uPeriod);
#endif
-#define RGFW_PROC_DEF(proc, name) if (name##SRC == NULL && proc != NULL) { \
- name##SRC = (PFN_##name)(RGFW_proc)GetProcAddress((proc), (#name)); \
- RGFW_ASSERT(name##SRC != NULL); \
- }
RGFW_format RGFW_nativeFormat(void) { return RGFW_formatBGRA8; }
@@ -10973,35 +11984,6 @@ void RGFW_window_captureMousePlatform(RGFW_window* win, RGFW_bool state) {
ClipCursor(&clipRect);
}
-#define RGFW_LOAD_LIBRARY(x, lib) if (x == NULL) { x = LoadLibraryA(lib); RGFW_ASSERT(x != NULL); }
-
-#ifdef RGFW_DIRECTX
-int RGFW_window_createSwapChain_DirectX(RGFW_window* win, IDXGIFactory* pFactory, IUnknown* pDevice, IDXGISwapChain** swapchain) {
- RGFW_ASSERT(win && pFactory && pDevice && swapchain);
-
- static DXGI_SWAP_CHAIN_DESC swapChainDesc;
- RGFW_MEMZERO(&swapChainDesc, sizeof(swapChainDesc));
- swapChainDesc.BufferCount = 2;
- swapChainDesc.BufferDesc.Width = win->w;
- swapChainDesc.BufferDesc.Height = win->h;
- swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
- swapChainDesc.OutputWindow = (HWND)win->src.window;
- swapChainDesc.SampleDesc.Count = 1;
- swapChainDesc.SampleDesc.Quality = 0;
- swapChainDesc.Windowed = TRUE;
- swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
-
- HRESULT hr = pFactory->lpVtbl->CreateSwapChain(pFactory, (IUnknown*)pDevice, &swapChainDesc, swapchain);
- if (FAILED(hr)) {
- RGFW_debugCallback(RGFW_typeError, RGFW_errDirectXContext, "Failed to create DirectX swap chain!");
- return -2;
- }
-
- return 0;
-}
-#endif
-
/* we're doing it with magic numbers because some keys are missing */
void RGFW_initKeycodesPlatform(void) {
_RGFW->keycodes[0x00B] = RGFW_key0;
@@ -11125,7 +12107,8 @@ void RGFW_initKeycodesPlatform(void) {
}
-i32 RGFW_initPlatform(void) {
+i32 RGFW_initPlatform(const char* className, RGFW_initFlags flags) {
+ RGFW_UNUSED(flags);
#ifndef RGFW_NO_DPI
#if (_WIN32_WINNT >= 0x0600)
SetProcessDPIAware();
@@ -11147,20 +12130,28 @@ i32 RGFW_initPlatform(void) {
RGFW_PROC_DEF(RGFW_dwm_dll, DwmSetWindowAttribute);
#endif
- RGFW_LOAD_LIBRARY(RGFW_wgl_dll, "opengl32.dll");
- #ifndef RGFW_NO_LOAD_WGL
- RGFW_PROC_DEF(RGFW_wgl_dll, wglCreateContext);
- RGFW_PROC_DEF(RGFW_wgl_dll, wglDeleteContext);
- RGFW_PROC_DEF(RGFW_wgl_dll, wglGetProcAddress);
- RGFW_PROC_DEF(RGFW_wgl_dll, wglMakeCurrent);
- RGFW_PROC_DEF(RGFW_wgl_dll, wglGetCurrentDC);
- RGFW_PROC_DEF(RGFW_wgl_dll, wglGetCurrentContext);
- RGFW_PROC_DEF(RGFW_wgl_dll, wglShareLists);
- #endif
+ _RGFW->instance = GetModuleHandleW(NULL);
+ MultiByteToWideChar(CP_UTF8, 0, className, -1, _RGFW->wideClassName, 255);
+
+ RGFW_MEMZERO(&_RGFW->wndClass, sizeof(_RGFW->wndClass));
+
+ _RGFW->wndClass.lpszClassName = _RGFW->wideClassName;
+ _RGFW->wndClass.hInstance = _RGFW->instance;
+ _RGFW->wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ _RGFW->wndClass.lpfnWndProc = WndProcW;
+ _RGFW->wndClass.cbClsExtra = sizeof(RGFW_window*);
+ _RGFW->wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
+ _RGFW->wndClass.hIcon = (HICON)LoadImageA(_RGFW->instance, "RGFW_ICON", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
+ if (_RGFW->wndClass.hIcon == NULL)
+ _RGFW->wndClass.hIcon = (HICON)LoadImageA(NULL, (LPCSTR)IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
+
+ RegisterClassW(&_RGFW->wndClass);
+
+ _RGFW->helperWindow = CreateWindowW(_RGFW->wndClass.lpszClassName, (wchar_t*)NULL, 0, 0, 0, 0, 0, 0, 0, _RGFW->instance, 0);
u8 RGFW_blk[] = { 0, 0, 0, 0 };
_RGFW->hiddenMouse = RGFW_createMouse(RGFW_blk, 1, 1, RGFW_formatRGBA8);
- return 1;
+ return 0;
}
RGFW_window* RGFW_createWindowPlatform(const char* name, RGFW_windowFlags flags, RGFW_window* win) {
@@ -11173,32 +12164,6 @@ RGFW_window* RGFW_createWindowPlatform(const char* name, RGFW_windowFlags flags,
win->src.aspectRatioW = 0;
win->src.aspectRatioH = 0;
- HINSTANCE inh = GetModuleHandleA(NULL);
-
- #ifndef __cplusplus
- WNDCLASSW Class = {0}; /*!< Setup the Window class. */
- #else
- WNDCLASSW Class = {};
- #endif
-
- if (_RGFW->className == NULL)
- _RGFW->className = (char*)name;
-
- wchar_t wide_class[256];
- MultiByteToWideChar(CP_UTF8, 0, _RGFW->className, -1, wide_class, 255);
-
- Class.lpszClassName = wide_class;
- Class.hInstance = inh;
- Class.hCursor = LoadCursor(NULL, IDC_ARROW);
- Class.lpfnWndProc = WndProcW;
- Class.cbClsExtra = sizeof(RGFW_window*);
-
- Class.hIcon = (HICON)LoadImageA(GetModuleHandleW(NULL), "RGFW_ICON", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
- if (Class.hIcon == NULL)
- Class.hIcon = (HICON)LoadImageA(NULL, (LPCSTR)IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
-
- RegisterClassW(&Class);
-
DWORD window_style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
if (!(flags & RGFW_windowNoBorder)) {
@@ -11211,20 +12176,13 @@ RGFW_window* RGFW_createWindowPlatform(const char* name, RGFW_windowFlags flags,
wchar_t wide_name[256];
MultiByteToWideChar(CP_UTF8, 0, name, -1, wide_name, 255);
- HWND dummyWin = CreateWindowW(Class.lpszClassName, (wchar_t*)wide_name, window_style, win->x, win->y, win->w, win->h, 0, 0, inh, 0);
-
-#ifdef RGFW_OPENGL
- RGFW_win32_loadOpenGLFuncs(dummyWin);
-#endif
-
- DestroyWindow(dummyWin);
RECT rect = { 0, 0, win->w, win->h};
DWORD style = RGFW_winapi_window_getStyle(win, flags);
DWORD exStyle = RGFW_winapi_window_getExStyle(win, flags);
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
- win->src.window = CreateWindowW(Class.lpszClassName, (wchar_t*)wide_name, window_style, win->x + rect.left, win->y + rect.top, rect.right - rect.left, rect.bottom - rect.top, 0, 0, inh, 0);
+ win->src.window = CreateWindowW(_RGFW->wndClass.lpszClassName, (wchar_t*)wide_name, window_style, win->x + rect.left, win->y + rect.top, rect.right - rect.left, rect.bottom - rect.top, 0, 0, _RGFW->instance, 0);
SetPropW(win->src.window, L"RGFW", win);
RGFW_window_resize(win, win->w, win->h); /* so WM_GETMINMAXINFO gets called again */
@@ -11309,57 +12267,15 @@ void RGFW_window_raise(RGFW_window* win) {
SetWindowPos(win->src.window, HWND_TOP, win->x, win->y, win->w, win->h, SWP_NOSIZE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
}
-void RGFW_window_setFullscreen(RGFW_window* win, RGFW_bool fullscreen) {
- RGFW_ASSERT(win != NULL);
-
- RGFW_monitor* mon = RGFW_window_getMonitor(win);
-
- if (fullscreen == RGFW_FALSE) {
- RGFW_monitor_setMode(mon, &win->internal.oldMode);
-
- RGFW_window_setBorder(win, 1);
+void RGFW_window_setFullscreenPlatform(RGFW_window* win, RGFW_bool fullscreen) { RGFW_UNUSED(win); RGFW_UNUSED(fullscreen); }
- RECT rect = { 0, 0, win->internal.oldW, win->internal.oldH};
- DWORD style = RGFW_winapi_window_getStyle(win, win->internal.flags);
- DWORD exStyle = RGFW_winapi_window_getExStyle(win, win->internal.flags);
- AdjustWindowRectEx(&rect, style, FALSE, exStyle);
- SetWindowPos(win->src.window, HWND_TOP, win->internal.oldX, win->internal.oldY, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
-
- win->internal.flags &= ~(u32)RGFW_windowFullscreen;
- win->x = win->internal.oldX;
- win->y = win->internal.oldY;
- win->w = win->internal.oldW;
- win->h = win->internal.oldH;
- return;
- }
-
- win->internal.oldX = win->x;
- win->internal.oldY = win->y;
- win->internal.oldW = win->w;
- win->internal.oldH = win->h;
- win->internal.oldMode = mon->mode;
- win->internal.flags |= RGFW_windowFullscreen;
-
- RGFW_window_setBorder(win, 0);
-
- SetWindowPos(win->src.window, HWND_TOPMOST, (i32)mon->x, (i32)mon->y, 0, 0, SWP_NOOWNERZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOSIZE);
- win->x = mon->x;
- win->y = mon->y;
-
- RGFW_monitor_scaleToWindow(mon, win);
- SetWindowPos(win->src.window, HWND_TOPMOST, 0, 0, (i32)mon->mode.w, (i32)mon->mode.h, SWP_NOOWNERZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE);
- win->w = mon->mode.w;
- win->h = mon->mode.h;
-}
-
-void RGFW_window_maximize(RGFW_window* win) {
+void RGFW_window_maximizePlatform(RGFW_window* win) {
RGFW_ASSERT(win != NULL);
RGFW_window_hide(win);
ShowWindow(win->src.window, SW_MAXIMIZE);
- RGFW_window_fetchSize(win, NULL, NULL);
}
-void RGFW_window_minimize(RGFW_window* win) {
+void RGFW_window_minimizePlatform(RGFW_window* win) {
RGFW_ASSERT(win != NULL);
ShowWindow(win->src.window, SW_MINIMIZE);
}
@@ -11375,14 +12291,14 @@ void RGFW_window_setOpacity(RGFW_window* win, u8 opacity) {
SetLayeredWindowAttributes(win->src.window, 0, opacity, LWA_ALPHA);
}
-void RGFW_window_restore(RGFW_window* win) { RGFW_window_show(win); }
+void RGFW_window_restorePlatform(RGFW_window* win) { RGFW_UNUSED(win); }
RGFW_bool RGFW_window_isFloating(RGFW_window* win) {
return (GetWindowLongPtr(win->src.window, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
}
void RGFW_stopCheckEvents(void) {
- PostMessageW(_RGFW->root->src.window, WM_NULL, 0, 0);
+ PostMessageW(_RGFW->helperWindow, WM_NULL, 0, 0);
}
void RGFW_waitForEvent(i32 waitMS) {
@@ -11404,9 +12320,15 @@ RGFW_key RGFW_physicalToMappedKey(RGFW_key key) {
if (result == 1 && charBuffer[0] < 256) {
return (RGFW_key)charBuffer[0];
- }
+ }
switch (vk) {
+ case VK_BACK: return RGFW_keyBackSpace;
+ case VK_TAB: return RGFW_keyTab;
+ /* VK_RETURN can be either RGFW_keyReturn or RGFW_keyPadReturn. RGFW can only give its best guess as to which key it should be. */
+ case VK_RETURN: return (key == RGFW_keyPadReturn) ? RGFW_keyPadReturn : RGFW_keyReturn;
+ case VK_ESCAPE: return RGFW_keyEscape;
+ case VK_DELETE: return RGFW_keyDelete;
case VK_F1: return RGFW_keyF1;
case VK_F2: return RGFW_keyF2;
case VK_F3: return RGFW_keyF3;
@@ -11456,7 +12378,6 @@ RGFW_key RGFW_physicalToMappedKey(RGFW_key key) {
case VK_SUBTRACT: return RGFW_keyPadMinus;
case VK_MULTIPLY: return RGFW_keyPadMultiply;
case VK_DIVIDE: return RGFW_keyPadSlash;
- case VK_RETURN: return RGFW_keyPadReturn;
case VK_DECIMAL: return RGFW_keyPadPeriod;
case VK_NUMPAD0: return RGFW_keyPad0;
case VK_NUMPAD1: return RGFW_keyPad1;
@@ -11470,7 +12391,7 @@ RGFW_key RGFW_physicalToMappedKey(RGFW_key key) {
case VK_NUMPAD9: return RGFW_keyPad9;
case VK_SNAPSHOT: return RGFW_keyPrintScreen;
case VK_PAUSE: return RGFW_keyPause;
- default: return RGFW_keyNULL;
+ default: break;
}
return RGFW_keyNULL;
@@ -11490,6 +12411,15 @@ void RGFW_pollEvents(void) {
RGFW_resetPrevState();
MSG msg;
while (PeekMessageA(&msg, NULL, 0u, 0u, PM_REMOVE)) {
+ if (msg.message == WM_QUIT) {
+ RGFW_window* cur = _RGFW->root;
+ while (cur) {
+ RGFW_window* next = cur->next;
+ RGFW_windowCloseCallback(cur);
+ cur = next;
+ }
+ }
+
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
@@ -11503,11 +12433,8 @@ RGFW_bool RGFW_window_isHidden(RGFW_window* win) {
RGFW_bool RGFW_window_isMinimized(RGFW_window* win) {
RGFW_ASSERT(win != NULL);
- #ifndef __cplusplus
- WINDOWPLACEMENT placement = {0};
- #else
- WINDOWPLACEMENT placement = {};
- #endif
+ WINDOWPLACEMENT placement;
+ RGFW_MEMZERO(&placement, sizeof(placement));
GetWindowPlacement(win->src.window, &placement);
return placement.showCmd == SW_SHOWMINIMIZED;
}
@@ -11515,16 +12442,14 @@ RGFW_bool RGFW_window_isMinimized(RGFW_window* win) {
RGFW_bool RGFW_window_isMaximized(RGFW_window* win) {
RGFW_ASSERT(win != NULL);
- #ifndef __cplusplus
- WINDOWPLACEMENT placement = {0};
- #else
- WINDOWPLACEMENT placement = {};
- #endif
+ WINDOWPLACEMENT placement;
+ RGFW_MEMZERO(&placement, sizeof(placement));
GetWindowPlacement(win->src.window, &placement);
return placement.showCmd == SW_SHOWMAXIMIZED || IsZoomed(win->src.window);
}
RGFW_bool RGFW_monitor_getWorkarea(RGFW_monitor* monitor, i32* x, i32* y, i32* width, i32* height) {
+ RGFW_ASSERT(monitor != NULL);
MONITORINFOEX mi;
mi.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfoA(monitor->node->hMonitor, (LPMONITORINFO)&mi);
@@ -11538,6 +12463,7 @@ RGFW_bool RGFW_monitor_getWorkarea(RGFW_monitor* monitor, i32* x, i32* y, i32* w
}
size_t RGFW_monitor_getGammaRampPtr(RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
+ RGFW_ASSERT(monitor != NULL);
WORD values[3][256];
HDC dc = CreateDCW(L"DISPLAY", monitor->node->adapterName, NULL, NULL);
@@ -11554,6 +12480,7 @@ size_t RGFW_monitor_getGammaRampPtr(RGFW_monitor* monitor, RGFW_gammaRamp* ramp)
}
RGFW_bool RGFW_monitor_setGammaRamp(RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
+ RGFW_ASSERT(monitor != NULL);
WORD values[3][256];
if (ramp->count != 256) {
RGFW_debugCallback(RGFW_typeError, RGFW_errX11, "Win32: Gamma ramp size must be 256");
@@ -11609,7 +12536,8 @@ void RGFW_win32_getMode(DEVMODEW* dm, RGFW_monitorMode* mode) {
}
}
-size_t RGFW_monitor_getModesPtr(RGFW_monitor* monitor, RGFW_monitorMode** modes){
+size_t RGFW_monitor_getModesPtr(RGFW_monitor* monitor, RGFW_monitorMode** modes) {
+ RGFW_ASSERT(monitor != NULL);
size_t count = 0;
DWORD modeIndex = 0;
@@ -11654,8 +12582,8 @@ size_t RGFW_monitor_getModesPtr(RGFW_monitor* monitor, RGFW_monitorMode** modes)
return count;
}
-RGFWDEF void RGFW_win32_createMonitor(DISPLAY_DEVICEW* adapter, DISPLAY_DEVICEW* dd);
-void RGFW_win32_createMonitor(DISPLAY_DEVICEW* adapter, DISPLAY_DEVICEW* dd) {
+RGFWDEF void RGFW_win32_initMonitor(DISPLAY_DEVICEW* adapter, RGFW_monitorNode* node);
+void RGFW_win32_initMonitor(DISPLAY_DEVICEW* adapter, RGFW_monitorNode* node) {
DEVMODEW dm;
ZeroMemory(&dm, sizeof(dm));
dm.dmSize = sizeof(dm);
@@ -11664,14 +12592,6 @@ void RGFW_win32_createMonitor(DISPLAY_DEVICEW* adapter, DISPLAY_DEVICEW* dd) {
return;
}
- RGFW_monitorNode* node = RGFW_monitors_add(NULL);
-
- wcscpy(node->adapterName, adapter->DeviceName);
- wcscpy(node->deviceName, dd->DeviceName);
-
- RGFW_createUTF8FromWideStringWin32(dd->DeviceString, node->mon.name, sizeof(node->mon.name));
- node->mon.name[sizeof(node->mon.name) - 1] = '\0';
-
RECT rect;
rect.left = (LONG)dm.dmPosition.x;
rect.top = (LONG)dm.dmPosition.y;
@@ -11689,9 +12609,9 @@ void RGFW_win32_createMonitor(DISPLAY_DEVICEW* adapter, DISPLAY_DEVICEW* dd) {
node->mon.y = monitorInfo.rcMonitor.top;
HDC hdc = CreateDCW(monitorInfo.szDevice, NULL, NULL, NULL);
- /* get pixels per inch */
+
float dpiX = (float)GetDeviceCaps(hdc, LOGPIXELSX);
- float dpiY = (float)GetDeviceCaps(hdc, LOGPIXELSX);
+ float dpiY = (float)GetDeviceCaps(hdc, LOGPIXELSY);
node->mon.scaleX = dpiX / 96.0f;
node->mon.scaleY = dpiY / 96.0f;
@@ -11717,6 +12637,18 @@ void RGFW_win32_createMonitor(DISPLAY_DEVICEW* adapter, DISPLAY_DEVICEW* dd) {
if (monitorInfo.dwFlags & MONITORINFOF_PRIMARY) {
_RGFW->monitors.primary = node;
}
+}
+
+RGFWDEF void RGFW_win32_createMonitor(DISPLAY_DEVICEW* adapter, DISPLAY_DEVICEW* dd);
+void RGFW_win32_createMonitor(DISPLAY_DEVICEW* adapter, DISPLAY_DEVICEW* dd) {
+ RGFW_monitorNode* node = RGFW_monitors_add(NULL);
+ RGFW_win32_initMonitor(adapter, node);
+
+ wcscpy(node->adapterName, adapter->DeviceName);
+ wcscpy(node->deviceName, dd->DeviceName);
+
+ i32 size = RGFW_createUTF8FromWideStringWin32(dd->DeviceString, node->mon.name, sizeof(node->mon.name));
+ node->mon.name[size - 1] = '\0';
RGFW_monitorCallback(_RGFW->root, &node->mon, RGFW_TRUE);
}
@@ -11758,7 +12690,7 @@ void RGFW_pollMonitors(void) {
for (node = _RGFW->monitors.list.head; node; node = node->next) {
if (node->disconnected == RGFW_TRUE && wcscmp(node->deviceName, dd.DeviceName) == 0) {
node->disconnected = RGFW_FALSE;
- EnumDisplayMonitors(NULL, NULL, RGFW_win32_getMonitorHandle, (LPARAM) &node->mon);
+ RGFW_win32_initMonitor(&adapter, node);
break;
}
}
@@ -11776,6 +12708,7 @@ void RGFW_pollMonitors(void) {
for (node = _RGFW->monitors.list.head; node; node = node->next) {
if (node->disconnected == RGFW_TRUE && wcscmp(node->adapterName, adapter.DeviceName) == 0) {
node->disconnected = RGFW_FALSE;
+ RGFW_win32_initMonitor(&adapter, node);
break;
}
}
@@ -11783,14 +12716,16 @@ void RGFW_pollMonitors(void) {
if (node) {
continue;
}
-
- RGFW_win32_createMonitor(&adapter, NULL);
}
}
RGFW_monitors_refresh();
}
+void RGFW_monitorNode_free(RGFW_monitorNode* node) {
+ RGFW_ASSERT(node);
+}
+
RGFW_monitor* RGFW_window_getMonitor(RGFW_window* win) {
HMONITOR src = MonitorFromWindow(win->src.window, MONITOR_DEFAULTTOPRIMARY);
RGFW_monitorNode* node = _RGFW->monitors.list.head;
@@ -11805,6 +12740,7 @@ RGFW_monitor* RGFW_window_getMonitor(RGFW_window* win) {
}
RGFW_bool RGFW_monitor_setMode(RGFW_monitor* mon, RGFW_monitorMode* mode) {
+ RGFW_ASSERT(mon != NULL);
DEVMODEW dm;
ZeroMemory(&dm, sizeof(dm));
dm.dmSize = sizeof(dm);
@@ -11822,6 +12758,7 @@ RGFW_bool RGFW_monitor_setMode(RGFW_monitor* mon, RGFW_monitorMode* mode) {
if (ChangeDisplaySettingsExW(mon->node->adapterName, &dm, NULL, CDS_TEST, NULL) == DISP_CHANGE_SUCCESSFUL) {
if (ChangeDisplaySettingsExW(mon->node->adapterName, &dm, NULL, CDS_UPDATEREGISTRY, NULL) == DISP_CHANGE_SUCCESSFUL) {
RGFW_win32_getMode(&dm, &mon->mode);
+ mon->mode = *mode;
return RGFW_TRUE;
}
return RGFW_FALSE;
@@ -11829,7 +12766,8 @@ RGFW_bool RGFW_monitor_setMode(RGFW_monitor* mon, RGFW_monitorMode* mode) {
}
RGFW_bool RGFW_monitor_requestMode(RGFW_monitor* mon, RGFW_monitorMode* mode, RGFW_modeRequest request) {
-HMONITOR src = mon->node->hMonitor;
+ RGFW_ASSERT(mon != NULL);
+ HMONITOR src = mon->node->hMonitor;
MONITORINFOEX monitorInfo;
monitorInfo.cbSize = sizeof(MONITORINFOEX);
@@ -11968,9 +12906,10 @@ void RGFW_window_hide(RGFW_window* win) {
ShowWindow(win->src.window, SW_HIDE);
}
-void RGFW_window_show(RGFW_window* win) {
- if (win->internal.flags & RGFW_windowFocusOnShow) RGFW_window_focus(win);
- ShowWindow(win->src.window, SW_RESTORE);
+void RGFW_window_showPlatform(RGFW_window* win) {
+ if (!(win->internal.flags & RGFW_windowMaximize)) {
+ ShowWindow(win->src.window, SW_RESTORE);
+ }
}
void RGFW_window_flash(RGFW_window* win, RGFW_flashRequest request) {
@@ -12004,21 +12943,25 @@ void RGFW_window_flash(RGFW_window* win, RGFW_flashRequest request) {
#define RGFW_FREE_LIBRARY(x) if (x != NULL) FreeLibrary(x); x = NULL;
void RGFW_deinitPlatform(void) {
#ifndef RGFW_NO_DPI
- RGFW_FREE_LIBRARY(RGFW_Shcore_dll);
+ RGFW_FREE_LIBRARY(RGFW_Shcore_dll);
#endif
#ifndef RGFW_NO_WINMM
- timeEndPeriod(1);
- #ifndef RGFW_NO_LOAD_WINMM
- RGFW_FREE_LIBRARY(RGFW_winmm_dll);
- #endif
+ timeEndPeriod(1);
+ #ifndef RGFW_NO_LOAD_WINMM
+ RGFW_FREE_LIBRARY(RGFW_winmm_dll);
+ #endif
#endif
- RGFW_FREE_LIBRARY(RGFW_wgl_dll);
+ if (_RGFW->helperWindow)
+ DestroyWindow(_RGFW->helperWindow);
- RGFW_freeMouse(_RGFW->hiddenMouse);
-}
+ if (_RGFW->instance)
+ UnregisterClassW(_RGFW->wndClass.lpszClassName, _RGFW->instance);
+ if (_RGFW->hiddenMouse)
+ RGFW_freeMouse(_RGFW->hiddenMouse);
+}
void RGFW_window_closePlatform(RGFW_window* win) {
RemovePropW(win->src.window, L"RGFW");
@@ -12029,19 +12972,16 @@ void RGFW_window_closePlatform(RGFW_window* win) {
if (win->src.hIconBig) DestroyIcon(win->src.hIconBig);
}
-void RGFW_window_move(RGFW_window* win, i32 x, i32 y) {
- RGFW_ASSERT(win != NULL);
-
- win->x = x;
- win->y = y;
- SetWindowPos(win->src.window, HWND_TOP, win->x, win->y, 0, 0, SWP_NOSIZE);
+void RGFW_window_movePlatform(RGFW_window* win, i32 x, i32 y) {
+ SetWindowPos(win->src.window, HWND_TOP, x, y, 0, 0, SWP_NOSIZE);
}
-void RGFW_window_resize(RGFW_window* win, i32 w, i32 h) {
- RGFW_ASSERT(win != NULL);
+void RGFW_window_resizePlatform(RGFW_window* win, i32 w, i32 h) {
+ if (win->internal.flags & RGFW_windowNoResize) {
+ win->src.minSizeW = win->src.maxSizeW = w;
+ win->src.minSizeH = win->src.maxSizeH = h;
+ }
- win->w = w;
- win->h = h;
RECT rect = { 0, 0, w, h};
DWORD style = RGFW_winapi_window_getStyle(win, win->internal.flags);
DWORD exStyle = RGFW_winapi_window_getExStyle(win, win->internal.flags);
@@ -12115,69 +13055,84 @@ RGFW_bool RGFW_window_setIconEx(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_f
#endif
}
-RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity) {
+RGFW_bool RGFW_readClipboardPtr(RGFW_dataTransferType requestedType, u8* buffer, size_t capacity, RGFW_dataTransfer* data) {
+ RGFW_ASSERT(data != NULL);
+
+ if (requestedType != RGFW_dataText) return RGFW_FALSE;
+
/* Open the clipboard */
- if (OpenClipboard(NULL) == 0)
- return -1;
+ size_t retry = 0;
+ BOOL isOpen = FALSE;
+ while (isOpen == FALSE && retry < 3) {
+ isOpen = OpenClipboard(NULL);
+ retry += 1;
+ }
+
+ if (isOpen == FALSE) return RGFW_FALSE;
/* Get the clipboard data as a Unicode string */
HANDLE hData = GetClipboardData(CF_UNICODETEXT);
if (hData == NULL) {
CloseClipboard();
- return -1;
+ return RGFW_FALSE;
}
wchar_t* wstr = (wchar_t*) GlobalLock(hData);
- RGFW_ssize_t textLen = 0;
+ RGFW_bool ret = RGFW_TRUE;
- {
- setlocale(LC_ALL, "en_US.UTF-8");
-
- textLen = (RGFW_ssize_t)wcstombs(NULL, wstr, 0) + 1;
- if (str != NULL && (RGFW_ssize_t)strCapacity <= textLen - 1)
- textLen = 0;
+ i32 length = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
+ if (length <= 0) return RGFW_FALSE;
- if (str != NULL && textLen) {
- if (textLen > 1)
- wcstombs(str, wstr, (size_t)(textLen));
+ data->length = (size_t)length;
+ data->type = RGFW_dataText;
- str[textLen - 1] = '\0';
- }
+ if (buffer != NULL && capacity < data->length) {
+ ret = RGFW_FALSE;
+ } else if (buffer != NULL && data->length) {
+ if (WideCharToMultiByte(CP_UTF8, 0, wstr, -1, (char*)buffer, length, NULL, NULL) <= 0) return RGFW_FALSE;
+ data->data = (const char*)buffer;
}
/* Release the clipboard data */
GlobalUnlock(hData);
CloseClipboard();
- return textLen;
+ return ret;
}
-void RGFW_writeClipboard(const char* text, u32 textLen) {
- HANDLE object;
- WCHAR* buffer;
-
- object = GlobalAlloc(GMEM_MOVEABLE, (1 + textLen) * sizeof(WCHAR));
+RGFW_bool RGFW_writeClipboard(const RGFW_dataTransfer* data) {
+ RGFW_ASSERT(data != NULL);
+ HANDLE object = GlobalAlloc(GMEM_MOVEABLE, data->length * sizeof(WCHAR));
if (!object)
- return;
+ return RGFW_FALSE;
- buffer = (WCHAR*) GlobalLock(object);
+ WCHAR* buffer = (WCHAR*) GlobalLock(object);
if (!buffer) {
GlobalFree(object);
- return;
+ return RGFW_FALSE;
}
- MultiByteToWideChar(CP_UTF8, 0, text, -1, buffer, (i32)textLen);
+ MultiByteToWideChar(CP_UTF8, 0, data->data, -1, buffer, (i32)data->length);
GlobalUnlock(object);
- if (!OpenClipboard(_RGFW->root->src.window)) {
+ size_t retry = 0;
+ BOOL isOpen = FALSE;
+ while (isOpen == FALSE && retry < 3) {
+ isOpen = OpenClipboard(NULL);
+ retry += 1;
+ }
+
+ if (isOpen == FALSE) {
GlobalFree(object);
- return;
+ return RGFW_FALSE;
}
EmptyClipboard();
SetClipboardData(CF_UNICODETEXT, object);
CloseClipboard();
+
+ return RGFW_TRUE;
}
void RGFW_window_moveMouse(RGFW_window* win, i32 x, i32 y) {
@@ -12187,6 +13142,36 @@ void RGFW_window_moveMouse(RGFW_window* win, i32 x, i32 y) {
SetCursorPos(x, y);
}
+#ifdef RGFW_DIRECTX
+i32 RGFW_window_createSwapChain_DirectX(RGFW_window* win, IDXGIFactory* pFactory, IUnknown* pDevice, IDXGISwapChain** swapchain) {
+ RGFW_ASSERT(win && pFactory && pDevice && swapchain);
+
+ DXGI_SWAP_CHAIN_DESC swapChainDesc;
+ RGFW_MEMZERO(&swapChainDesc, sizeof(swapChainDesc));
+ swapChainDesc.BufferCount = 2;
+ swapChainDesc.BufferDesc.Width = win->w;
+ swapChainDesc.BufferDesc.Height = win->h;
+ swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ swapChainDesc.OutputWindow = (HWND)win->src.window;
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.Windowed = TRUE;
+ swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
+#ifdef __cplusplus
+ HRESULT hr = pFactory->CreateSwapChain(pDevice, &swapChainDesc, swapchain);
+#else
+ HRESULT hr = pFactory->lpVtbl->CreateSwapChain(pFactory, (IUnknown*)pDevice, &swapChainDesc, swapchain);
+#endif
+ if (FAILED(hr)) {
+ RGFW_debugCallback(RGFW_typeError, RGFW_errDirectXContext, "Failed to create DirectX swap chain!");
+ return -2;
+ }
+
+ return 0;
+}
+#endif
+
#ifdef RGFW_OPENGL
RGFW_bool RGFW_extensionSupportedPlatform_OpenGL(const char * extension, size_t len) {
const char* extensions = NULL;
@@ -12195,97 +13180,27 @@ RGFW_bool RGFW_extensionSupportedPlatform_OpenGL(const char * extension, size_t
RGFW_proc proc2 = RGFW_getProcAddress_OpenGL("wglGetExtensionsStringEXT");
if (proc)
- extensions = ((const char* (*)(HDC))proc)(wglGetCurrentDC());
+ extensions = ((const char* (*)(HDC))proc)(RGFW_wglGetCurrentDC());
else if (proc2)
extensions = ((const char*(*)(void))proc2)();
return extensions != NULL && RGFW_extensionSupportedStr(extensions, extension, len);
}
RGFW_proc RGFW_getProcAddress_OpenGL(const char* procname) {
- RGFW_proc proc = (RGFW_proc)wglGetProcAddress(procname);
+ RGFW_proc proc = (RGFW_proc)_RGFW->glGetProcAddress(procname);
if (proc)
return proc;
- return (RGFW_proc) GetProcAddress(RGFW_wgl_dll, procname);
+ return (RGFW_proc) GetProcAddress((HMODULE)_RGFW->nativeGL_handle, procname);
}
-void RGFW_win32_loadOpenGLFuncs(HWND dummyWin) {
- if (wglSwapIntervalEXT != NULL && wglChoosePixelFormatARB != NULL && wglChoosePixelFormatARB != NULL)
- return;
-
- HDC dummy_dc = GetDC(dummyWin);
- u32 pfd_flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
-
- PIXELFORMATDESCRIPTOR pfd = {sizeof(pfd), 1, pfd_flags, PFD_TYPE_RGBA, 32, 8, PFD_MAIN_PLANE, 32, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 32, 8, 0, PFD_MAIN_PLANE, 0, 0, 0, 0};
-
- int dummy_pixel_format = ChoosePixelFormat(dummy_dc, &pfd);
- SetPixelFormat(dummy_dc, dummy_pixel_format, &pfd);
-
- HGLRC dummy_context = wglCreateContext(dummy_dc);
-
- HGLRC cur = wglGetCurrentContext();
- wglMakeCurrent(dummy_dc, dummy_context);
-
- wglCreateContextAttribsARB = ((PFNWGLCREATECONTEXTATTRIBSARBPROC(WINAPI *)(const char*)) wglGetProcAddress)("wglCreateContextAttribsARB");
- wglChoosePixelFormatARB = ((PFNWGLCHOOSEPIXELFORMATARBPROC(WINAPI *)(const char*)) wglGetProcAddress)("wglChoosePixelFormatARB");
-
- wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)(RGFW_proc)wglGetProcAddress("wglSwapIntervalEXT");
- if (wglSwapIntervalEXT == NULL) {
- RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to load swap interval function");
- }
-
- wglMakeCurrent(dummy_dc, cur);
- wglDeleteContext(dummy_context);
- ReleaseDC(dummyWin, dummy_dc);
-}
-
-#define WGL_ACCELERATION_ARB 0x2003
-#define WGL_FULL_ACCELERATION_ARB 0x2027
-#define WGL_DRAW_TO_WINDOW_ARB 0x2001
-#define WGL_PIXEL_TYPE_ARB 0x2013
-#define WGL_TYPE_RGBA_ARB 0x202b
-#define WGL_SUPPORT_OPENGL_ARB 0x2010
-#define WGL_COLOR_BITS_ARB 0x2014
-#define WGL_DOUBLE_BUFFER_ARB 0x2011
-#define WGL_ALPHA_BITS_ARB 0x201b
-#define WGL_DEPTH_BITS_ARB 0x2022
-#define WGL_STENCIL_BITS_ARB 0x2023
-#define WGL_STEREO_ARB 0x2012
-#define WGL_AUX_BUFFERS_ARB 0x2024
-#define WGL_RED_BITS_ARB 0x2015
-#define WGL_GREEN_BITS_ARB 0x2017
-#define WGL_BLUE_BITS_ARB 0x2019
-#define WGL_ACCUM_RED_BITS_ARB 0x201e
-#define WGL_ACCUM_GREEN_BITS_ARB 0x201f
-#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
-#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
-#define WGL_COLORSPACE_SRGB_EXT 0x3089
-#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
-#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
-#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0x0000
-#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
-#define WGL_CONTEXT_FLAGS_ARB 0x2094
-#define WGL_ACCESS_READ_WRITE_NV 0x00000001
-#define WGL_COVERAGE_SAMPLES_NV 0x2042
-#define WGL_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004
-#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
-#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
-#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
-#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
-#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
-#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
-#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9
-#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
-#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001
-#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
-
-RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx, RGFW_glHints* hints) {
+RGFW_bool RGFW_createContextPtr_OpenGL(RGFW_glContext* ctx, RGFW_glHints* hints) {
const char flushControl[] = "WGL_ARB_context_flush_control";
const char noError[] = "WGL_ARB_create_context_no_error";
const char robustness[] = "WGL_ARB_create_context_robustness";
- win->src.ctx.native = ctx;
- win->src.gfxType = RGFW_gfxNativeOpenGL;
+ HWND dummyWindow = CreateWindowW(_RGFW->wndClass.lpszClassName, (wchar_t*)NULL, 0, 0, 0, 0, 0, 0, 0, _RGFW->instance, 0);
+ HDC hdc = GetDC(dummyWindow);
PIXELFORMATDESCRIPTOR pfd;
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
@@ -12293,9 +13208,9 @@ RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext*
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.iLayerType = PFD_MAIN_PLANE;
- pfd.cColorBits = 32;
- pfd.cAlphaBits = 8;
- pfd.cDepthBits = 24;
+ pfd.cColorBits = (BYTE)(hints->red + hints->green + hints->blue + hints->alpha);
+ pfd.cAlphaBits = (BYTE)hints->alpha;
+ pfd.cDepthBits = (BYTE)hints->depth;
pfd.cStencilBits = (BYTE)hints->stencil;
pfd.cAuxBuffers = (BYTE)hints->auxBuffers;
if (hints->stereo) pfd.dwFlags |= PFD_STEREO;
@@ -12305,8 +13220,8 @@ RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext*
pfd.dwFlags |= PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED;
/* get pixel format, default to a basic pixel format */
- int pixel_format = ChoosePixelFormat(win->src.hdc, &pfd);
- if (wglChoosePixelFormatARB != NULL) {
+ ctx->format = ChoosePixelFormat(hdc, &pfd);
+ if (RGFW_wglChoosePixelFormatARB != NULL) {
i32 pixel_format_attribs[50];
RGFW_attribStack stack;
RGFW_attribStack_init(&stack, pixel_format_attribs, 50);
@@ -12315,7 +13230,7 @@ RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext*
RGFW_attribStack_pushAttribs(&stack, WGL_DRAW_TO_WINDOW_ARB, 1);
RGFW_attribStack_pushAttribs(&stack, WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB);
RGFW_attribStack_pushAttribs(&stack, WGL_SUPPORT_OPENGL_ARB, 1);
- RGFW_attribStack_pushAttribs(&stack, WGL_COLOR_BITS_ARB, 32);
+ RGFW_attribStack_pushAttribs(&stack, WGL_COLOR_BITS_ARB, hints->red + hints->green + hints->blue + hints->alpha);
RGFW_attribStack_pushAttribs(&stack, WGL_DOUBLE_BUFFER_ARB, 1);
RGFW_attribStack_pushAttribs(&stack, WGL_ALPHA_BITS_ARB, hints->alpha);
RGFW_attribStack_pushAttribs(&stack, WGL_DEPTH_BITS_ARB, hints->depth);
@@ -12337,24 +13252,28 @@ RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext*
RGFW_attribStack_pushAttribs(&stack, WGL_COLORSPACE_SRGB_EXT, hints->sRGB);
}
- RGFW_attribStack_pushAttribs(&stack, WGL_COVERAGE_SAMPLES_NV, hints->samples);
+ if (hints->samples) {
+ RGFW_attribStack_pushAttribs(&stack, WGL_SAMPLE_BUFFERS_ARB, 1);
+ RGFW_attribStack_pushAttribs(&stack, WGL_SAMPLES_ARB, hints->samples);
+ }
RGFW_attribStack_pushAttribs(&stack, 0, 0);
int new_pixel_format;
UINT num_formats;
- wglChoosePixelFormatARB(win->src.hdc, pixel_format_attribs, 0, 1, &new_pixel_format, &num_formats);
+ RGFW_wglChoosePixelFormatARB(hdc, pixel_format_attribs, 0, 1, &new_pixel_format, &num_formats);
if (!num_formats)
RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to create a pixel format for WGL");
- else pixel_format = new_pixel_format;
+ else ctx->format = new_pixel_format;
}
+
PIXELFORMATDESCRIPTOR suggested;
- if (!DescribePixelFormat(win->src.hdc, pixel_format, sizeof(suggested), &suggested) ||
- !SetPixelFormat(win->src.hdc, pixel_format, &pfd))
+ if (!DescribePixelFormat(hdc, ctx->format, sizeof(suggested), &suggested) ||
+ !SetPixelFormat(hdc, ctx->format, &suggested))
RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to set the WGL pixel format");
- if (wglCreateContextAttribsARB != NULL) {
+ if (RGFW_wglCreateContextAttribsARB != NULL) {
/* create OpenGL/WGL context for the specified version */
i32 attribs[40];
RGFW_attribStack stack;
@@ -12398,41 +13317,109 @@ RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext*
RGFW_attribStack_pushAttribs(&stack, 0, 0);
- win->src.ctx.native->ctx = (HGLRC)wglCreateContextAttribsARB(win->src.hdc, NULL, attribs);
+ ctx->ctx = (HGLRC)RGFW_wglCreateContextAttribsARB(hdc, NULL, attribs);
}
- if (wglCreateContextAttribsARB == NULL || win->src.ctx.native->ctx == NULL) { /* fall back to a default context (probably OpenGL 2 or something) */
+ if (RGFW_wglCreateContextAttribsARB == NULL || ctx->ctx == NULL) { /* fall back to a default context (probably OpenGL 2 or something) */
RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to create an accelerated OpenGL Context.");
- win->src.ctx.native->ctx = wglCreateContext(win->src.hdc);
+ ctx->ctx = RGFW_wglCreateContext(hdc);
}
- ReleaseDC(win->src.window, win->src.hdc);
- win->src.hdc = GetDC(win->src.window);
-
if (hints->share) {
- wglShareLists((HGLRC)RGFW_getCurrentContext_OpenGL(), hints->share->ctx);
+ RGFW_wglShareLists((HGLRC)RGFW_getCurrentContext_OpenGL(), hints->share->ctx);
}
- wglMakeCurrent(win->src.hdc, win->src.ctx.native->ctx);
+ DestroyWindow(dummyWindow);
+
RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context initalized.");
return RGFW_TRUE;
}
-void RGFW_window_deleteContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx) {
- wglDeleteContext((HGLRC) ctx->ctx); /*!< delete OpenGL context */
- win->src.ctx.native->ctx = NULL;
+RGFW_bool RGFW_window_setContext_OpenGL(RGFW_window* win, RGFW_glContext* ctx) {
+ RGFW_ASSERT(win);
+ if (ctx == NULL && win->src.ctx.native != NULL) {
+ RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL surface freed.");
+ win->src.ctx.native = NULL;
+
+ RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL window surface freed");
+ return RGFW_TRUE;
+ }
+
+ win->src.ctx.native = ctx;
+ win->src.gfxType = RGFW_gfxNativeOpenGL;
+
+ PIXELFORMATDESCRIPTOR suggested;
+ if (!DescribePixelFormat(win->src.hdc, ctx->format, sizeof(suggested), &suggested) ||
+ !SetPixelFormat(win->src.hdc, ctx->format, &suggested))
+ RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to set the WGL pixel format");
+
+ if (RGFW_wglMakeCurrent(win->src.hdc, win->src.ctx.native->ctx) == FALSE) {
+ /*
+ Windows may fail to set the pixel format if the window was already created,
+ this tries to make a new window as a fallback
+ */
+
+ int length = GetWindowTextLengthW(win->src.window);
+ char* name = NULL;
+ if (length > 0) {
+ WCHAR* buffer = (WCHAR*)RGFW_ALLOC(sizeof(WCHAR) * (size_t)(length));
+ if (GetWindowTextW(win->src.window, buffer, length) > 0) {
+ i32 clength = RGFW_createUTF8FromWideStringWin32(buffer, NULL, 0);
+ if (clength > 0) {
+ name = (char*)RGFW_ALLOC((size_t)clength + 1);
+ if (RGFW_createUTF8FromWideStringWin32(buffer, name, (size_t)clength) > 0) {
+ name[clength] = '\0';
+ } else {
+ RGFW_FREE(name);
+ name = NULL;
+ }
+ }
+ RGFW_FREE(buffer);
+ }
+ }
+
+ RGFW_window_closePlatform(win);
+ win = RGFW_createWindowPlatform(name ? name : "", win->internal.flags, win);
+
+ if (name) RGFW_FREE(name);
+
+ win->src.ctx.native = ctx;
+ win->src.gfxType = RGFW_gfxNativeOpenGL;
+
+ if (!DescribePixelFormat(win->src.hdc, ctx->format, sizeof(suggested), &suggested) ||
+ !SetPixelFormat(win->src.hdc, ctx->format, &suggested))
+ RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to set the WGL pixel format");
+
+ if (RGFW_wglMakeCurrent(win->src.hdc, win->src.ctx.native->ctx) == FALSE) {
+ RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "failed to create OpenGL surface.");
+ return RGFW_FALSE;
+ }
+ }
+
+ RGFW_window_swapInterval_OpenGL(win, 0);
+ RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL surface initalized.");
+ return RGFW_TRUE;
+}
+
+void RGFW_deleteContextPtr_OpenGL(RGFW_glContext* ctx) {
+ RGFW_wglDeleteContext((HGLRC) ctx->ctx); /*!< delete OpenGL context */
RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context freed.");
}
void RGFW_window_makeCurrentContext_OpenGL(RGFW_window* win) {
if (win == NULL)
- wglMakeCurrent(NULL, NULL);
+ RGFW_wglMakeCurrent(NULL, NULL);
else
- wglMakeCurrent(win->src.hdc, (HGLRC) win->src.ctx.native->ctx);
+ RGFW_wglMakeCurrent(win->src.hdc, (HGLRC) win->src.ctx.native->ctx);
}
void* RGFW_getCurrentContext_OpenGL(void) {
- return wglGetCurrentContext();
+ return RGFW_wglGetCurrentContext();
+}
+
+void* RGFW_getCurrentSurface_OpenGL(void) {
+ return RGFW_wglGetCurrentDC();
}
+
void RGFW_window_swapBuffers_OpenGL(RGFW_window* win) {
RGFW_ASSERT(win->src.ctx.native);
SwapBuffers(win->src.hdc);
@@ -12440,31 +13427,18 @@ void RGFW_window_swapBuffers_OpenGL(RGFW_window* win) {
void RGFW_window_swapInterval_OpenGL(RGFW_window* win, i32 swapInterval) {
RGFW_ASSERT(win != NULL);
- if (wglSwapIntervalEXT == NULL || wglSwapIntervalEXT(swapInterval) == FALSE)
- RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to set swap interval");
-}
-#endif
+ void* ctx = RGFW_getCurrentContext_OpenGL();
+ void* surf = RGFW_getCurrentSurface_OpenGL();
+ if (ctx != win->src.ctx.native->ctx || surf != win->src.hdc)
+ RGFW_wglMakeCurrent(win->src.hdc, (HGLRC) win->src.ctx.native->ctx);
-RGFW_bool RGFW_createUTF8FromWideStringWin32(const WCHAR* source, char* output, size_t max) {
- i32 size = 0;
- if (source == NULL) {
- return RGFW_FALSE;
- }
- size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
- if (!size) {
- return RGFW_FALSE;
- }
-
- if (size > (i32)max)
- size = (i32)max;
-
- if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, output, size, NULL, NULL)) {
- return RGFW_FALSE;
- }
+ if (RGFW_wglSwapIntervalEXT == NULL || RGFW_wglSwapIntervalEXT(swapInterval) == FALSE)
+ RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to set swap interval");
- output[size] = 0;
- return RGFW_TRUE;
+ if (ctx != win->src.ctx.native->ctx || surf != win->src.hdc)
+ RGFW_wglMakeCurrent((HDC)surf, (HGLRC)ctx);
}
+#endif
#ifdef RGFW_WEBGPU
WGPUSurface RGFW_window_createSurface_WebGPU(RGFW_window* window, WGPUInstance instance) {
@@ -12473,7 +13447,7 @@ WGPUSurface RGFW_window_createSurface_WebGPU(RGFW_window* window, WGPUInstance i
fromHwnd.chain.sType = WGPUSType_SurfaceSourceWindowsHWND;
fromHwnd.hwnd = window->src.window;
- fromHwnd.hinstance = GetModuleHandle(NULL);
+ fromHwnd.hinstance = _RGFW->instance;
surfaceDesc.nextInChain = (WGPUChainedStruct*)&fromHwnd.chain;
return wgpuInstanceCreateSurface(instance, &surfaceDesc);
@@ -12523,12 +13497,15 @@ PFN_LMGetKbdType LMGetKbdTypeSrc;
CFStringRef kTISPropertyUnicodeKeyLayoutDataSrc;
+#define RSGL_NSPasteboardTypeURL "public.url"
+#define RSGL_NSPasteboardTypeFileURL "public.file-url"
+#define RSGL_NSPasteboardTypeString "public.utf8-plain-text"
+
#ifndef __OBJC__
typedef CGRect NSRect;
typedef CGPoint NSPoint;
typedef CGSize NSSize;
-typedef const char* NSPasteboardType;
typedef unsigned long NSUInteger;
typedef long NSInteger;
typedef NSInteger NSModalResponse;
@@ -12538,19 +13515,19 @@ typedef enum NSRequestUserAttentionType {
NSInformationalRequest = 10
} NSRequestUserAttentionType;
-typedef enum NSApplicationActivationPolicy {
+typedef RGFW_ENUM(NSInteger, NSApplicationActivationPolicy) {
NSApplicationActivationPolicyRegular,
NSApplicationActivationPolicyAccessory,
NSApplicationActivationPolicyProhibited
-} NSApplicationActivationPolicy;
+};
-typedef RGFW_ENUM(u32, NSBackingStoreType) {
+typedef RGFW_ENUM(NSUInteger, NSBackingStoreType) {
NSBackingStoreRetained = 0,
NSBackingStoreNonretained = 1,
NSBackingStoreBuffered = 2
};
-typedef RGFW_ENUM(u32, NSWindowStyleMask) {
+typedef RGFW_ENUM(NSUInteger, NSWindowStyleMask) {
NSWindowStyleMaskBorderless = 0,
NSWindowStyleMaskTitled = 1 << 0,
NSWindowStyleMaskClosable = 1 << 1,
@@ -12566,9 +13543,7 @@ typedef RGFW_ENUM(u32, NSWindowStyleMask) {
NSWindowStyleMaskHUDWindow = 1 << 13
};
-#define NSPasteboardTypeString "public.utf8-plain-text"
-
-typedef RGFW_ENUM(i32, NSDragOperation) {
+typedef RGFW_ENUM(NSUInteger, NSDragOperation) {
NSDragOperationNone = 0,
NSDragOperationCopy = 1,
NSDragOperationLink = 2,
@@ -12608,8 +13583,6 @@ typedef RGFW_ENUM(NSInteger, NSWindowButton) {
NSWindowFullScreenButton = 7,
};
-#define NSPasteboardTypeURL "public.url"
-#define NSPasteboardTypeFileURL "public.file-url"
#define NSTrackingMouseEnteredAndExited 0x01
#define NSTrackingMouseMoved 0x02
#define NSTrackingCursorUpdate 0x04
@@ -12665,19 +13638,19 @@ enum {
NSOpenGLPFARemotePixelBuffer = 91,
};
-typedef RGFW_ENUM(u32, NSEventType) { /* various types of events */
+typedef RGFW_ENUM(NSUInteger, NSEventType) { /* various types of events */
NSEventTypeApplicationDefined = 15,
};
-typedef unsigned long long NSEventMask;
+typedef NSUInteger NSEventMask;
-typedef enum NSEventModifierFlags {
+typedef RGFW_ENUM(NSUInteger, NSEventModifierFlags) {
NSEventModifierFlagCapsLock = 1 << 16,
NSEventModifierFlagShift = 1 << 17,
NSEventModifierFlagControl = 1 << 18,
NSEventModifierFlagOption = 1 << 19,
NSEventModifierFlagCommand = 1 << 20,
NSEventModifierFlagNumericPad = 1 << 21
-} NSEventModifierFlags;
+};
typedef RGFW_ENUM(NSUInteger, NSBitmapFormat) {
NSBitmapFormatAlphaFirst = 1 << 0, /* 0 means is alpha last (RGBA, CMYKA, etc.) */
@@ -12731,6 +13704,17 @@ id NSString_stringWithUTF8String(const char* str) {
RGFWDEF float RGFW_cocoaYTransform(float y);
float RGFW_cocoaYTransform(float y) { return (float)(CGDisplayBounds(CGMainDisplayID()).size.height - (double)y - (double)1.0f); }
+RGFWDEF void RGFW_cocoaFetchRect(RGFW_window* win);
+void RGFW_cocoaFetchRect(RGFW_window* win) {
+ NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.window, sel_registerName("frame"));
+ NSRect content = ((NSRect(*)(id, SEL, NSRect))abi_objc_msgSend_stret)((id)win->src.window, sel_registerName("contentRectForFrameRect:"), frame);
+
+ win->x = (i32)content.origin.x;
+ win->y = (i32)RGFW_cocoaYTransform((float)(content.origin.y + content.size.height - 1));
+ win->w = (i32)content.size.width;
+ win->h = (i32)content.size.height;
+}
+
const char* NSString_to_char(id str);
const char* NSString_to_char(id str) {
return ((const char* (*)(id, SEL)) objc_msgSend) ((id)(id)str, sel_registerName("UTF8String"));
@@ -12772,8 +13756,8 @@ id* cstrToNSStringArray(char** strs, size_t len) {
return nstrs;
}
-const char* NSPasteboard_stringForType(id pasteboard, NSPasteboardType dataType, size_t* len);
-const char* NSPasteboard_stringForType(id pasteboard, NSPasteboardType dataType, size_t* len) {
+const char* NSPasteboard_stringForType(id pasteboard, const char* dataType, size_t* len);
+const char* NSPasteboard_stringForType(id pasteboard, const char* dataType, size_t* len) {
SEL func = sel_registerName("stringForType:");
id nsstr = NSString_stringWithUTF8String((const char*)dataType);
id nsString = ((id(*)(id, SEL, id))objc_msgSend)(pasteboard, func, nsstr);
@@ -12789,8 +13773,8 @@ id c_array_to_NSArray(void* array, size_t len) {
}
-void NSregisterForDraggedTypes(id view, NSPasteboardType* newTypes, size_t len);
-void NSregisterForDraggedTypes(id view, NSPasteboardType* newTypes, size_t len) {
+void NSregisterForDraggedTypes(id view, const char** newTypes, size_t len);
+void NSregisterForDraggedTypes(id view, const char** newTypes, size_t len) {
id* ntypes = cstrToNSStringArray((char**)newTypes, len);
id array = c_array_to_NSArray(ntypes, len);
@@ -12798,8 +13782,8 @@ void NSregisterForDraggedTypes(id view, NSPasteboardType* newTypes, size_t len)
NSRelease(array);
}
-NSInteger NSPasteBoard_declareTypes(id pasteboard, NSPasteboardType* newTypes, size_t len, void* owner);
-NSInteger NSPasteBoard_declareTypes(id pasteboard, NSPasteboardType* newTypes, size_t len, void* owner) {
+NSInteger NSPasteBoard_declareTypes(id pasteboard, const char** newTypes, size_t len, void* owner);
+NSInteger NSPasteBoard_declareTypes(id pasteboard, const char** newTypes, size_t len, void* owner) {
id* ntypes = cstrToNSStringArray((char**)newTypes, len);
SEL func = sel_registerName("declareTypes:owner:");
@@ -12813,8 +13797,6 @@ NSInteger NSPasteBoard_declareTypes(id pasteboard, NSPasteboardType* newTypes, s
return output;
}
-#define NSRetain(obj) objc_msgSend_void((id)obj, sel_registerName("retain"))
-
/*
End of cocoa wrapper
*/
@@ -12847,24 +13829,16 @@ static id RGFW__osxCustomInitWithRGFWWindow(id self, SEL _cmd, RGFW_window* win)
((void (*)(id, SEL))objc_msgSend)(self, sel_registerName("updateTrackingAreas"));
- ((void (*)(id, SEL, id))objc_msgSend)(
- self, sel_registerName("registerForDraggedTypes:"),
- ((id (*)(Class, SEL, id))objc_msgSend)(
- objc_getClass("NSArray"),
- sel_registerName("arrayWithObject:"),
- ((id (*)(Class, SEL, const char*))objc_msgSend)(
- objc_getClass("NSString"),
- sel_registerName("stringWithUTF8String:"),
- "public.url"
- )
- )
- );
- }
+ const char* types[] = {RSGL_NSPasteboardTypeURL, RSGL_NSPasteboardTypeFileURL, RSGL_NSPasteboardTypeString};
+ NSregisterForDraggedTypes((id)self, types, 3);
+
+ }
return self;
}
-static u32 RGFW_OnClose(id self) {
+static BOOL RGFW_osxWindowShouldClose(id self, SEL _cmd, id sender) {
+ RGFW_UNUSED(_cmd); RGFW_UNUSED(sender);
RGFW_window* win = NULL;
object_getInstanceVariable(self, (const char*)"RGFW_window", (void**)&win);
if (win == NULL) return true;
@@ -12873,9 +13847,47 @@ static u32 RGFW_OnClose(id self) {
return false;
}
-/* NOTE(EimaMei): Fixes the constant clicking when the app is running under a terminal. */
-static bool RGFW__osxAcceptsFirstResponder(void) { return true; }
-static bool RGFW__osxPerformKeyEquivalent(id event) { RGFW_UNUSED(event); return true; }
+static BOOL RGFW__osxAcceptsFirstResponder(id self, SEL _cmd) { RGFW_UNUSED(self); RGFW_UNUSED(_cmd); return true; }
+static BOOL RGFW__osxPerformKeyEquivalent(id self, SEL _cmd, id event) {
+ RGFW_UNUSED(_cmd);
+ RGFW_window* win = NULL;
+ object_getInstanceVariable(self, (const char*)"RGFW_window", (void**)&win);
+ if (win == NULL) return true;
+
+ /* claim and emit consumed key combinations so they aren't missed (hack borrowed from GLFW (I'm not giving it back)) */
+ u32 key = (u16)((u32(*)(id, SEL))objc_msgSend)(event, sel_registerName("keyCode"));
+ RGFW_key value = (u8)RGFW_apiKeyToRGFW(key);
+
+ u32 flags = (u32)((u32(*)(id, SEL))objc_msgSend)(event, sel_registerName("modifierFlags"));
+ RGFW_keyUpdateKeyModsEx(win,
+ ((u32)(flags & NSEventModifierFlagCapsLock) % 255),
+ ((flags & NSEventModifierFlagNumericPad) % 255),
+ ((flags & NSEventModifierFlagControl) % 255),
+ ((flags & NSEventModifierFlagOption) % 255),
+ ((flags & NSEventModifierFlagShift) % 255),
+ ((flags & NSEventModifierFlagCommand) % 255), 0);
+
+ RGFW_bool repeat = RGFW_isKeyDown(value);
+
+ if (win->internal.mod & RGFW_modControl) {
+ if (key == RGFW_keyTab || key == RGFW_keyEscape) {
+ RGFW_keyCallback(win, value, win->internal.mod, repeat, 1);
+ return YES;
+ }
+ }
+
+ if (win->internal.mod & RGFW_modSuper) {
+ if (key == RGFW_keyPeriod) {
+ RGFW_keyCallback(win, value, win->internal.mod, repeat, 1);
+ return YES;
+ }
+ }
+
+ struct objc_super s = { self, class_getSuperclass(object_getClass(self)) };
+ return ((bool (*)(struct objc_super*, SEL, id))objc_msgSendSuper)(&s, sel_registerName("performKeyEquivalent:"), event);
+}
+
+static BOOL RGFW__osxAcceptsFirstMouse(id self, SEL _cmd, id event) { RGFW_UNUSED(self); RGFW_UNUSED(_cmd); RGFW_UNUSED(event); return true; }
static NSDragOperation RGFW__osxDraggingEntered(id self, SEL sel, id sender) {
RGFW_UNUSED(sel);
@@ -12902,7 +13914,7 @@ static NSDragOperation RGFW__osxDraggingUpdated(id self, SEL sel, id sender) {
RGFW_dataDragCallback(win, RGFW_dataFile, RGFW_dndActionMove, (i32) p.x, (i32) (win->h - p.y));
return NSDragOperationCopy;
}
-static bool RGFW__osxPrepareForDragOperation(id self) {
+static BOOL RGFW__osxPrepareForDragOperation(id self) {
RGFW_window* win = NULL;
object_getInstanceVariable(self, "RGFW_window", (void**)&win);
if (win == NULL || (!(win->internal.enabledEvents & RGFW_dataDropFlag)))
@@ -12929,7 +13941,7 @@ static void RGFW__osxDraggingEnded(id self, SEL sel, id sender) {
return;
}
-static bool RGFW__osxPerformDragOperation(id self, SEL sel, id sender) {
+static BOOL RGFW__osxPerformDragOperation(id self, SEL sel, id sender) {
RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel);
RGFW_window* win = NULL;
object_getInstanceVariable(self, "RGFW_window", (void**)&win);
@@ -12952,17 +13964,25 @@ static bool RGFW__osxPerformDragOperation(id self, SEL sel, id sender) {
return 0;
}
- id fileURLs = objc_msgSend_id_id(pasteBoard, sel_registerName("propertyListForType:"), fileURLsType);
- int count = ((int (*)(id, SEL))objc_msgSend)(fileURLs, sel_registerName("count"));
+ id propertyList = objc_msgSend_id_id(pasteBoard, sel_registerName("propertyListForType:"), fileURLsType);
+
+ if (objc_msgSend_id_bool(propertyList, sel_registerName("isKindOfClass:"), objc_getClass("NSString"))) {
+ int string_count = ((int (*)(id, SEL))objc_msgSend)(propertyList , sel_registerName("length"));
+ const char *filePath = ((const char* (*)(id, SEL))objc_msgSend)(propertyList, sel_registerName("UTF8String"));
+ RGFW_dataDropCallback(win, filePath, (size_t)string_count + 1, RGFW_dataFile);
+ /*} if (objc_msgSend_id_bool(propertyList, sel_registerName("isKindOfClass:"), objc_getClass("NSData"))) { */
+ } if (objc_msgSend_id_bool(propertyList, sel_registerName("isKindOfClass:"), objc_getClass("NSArray")) == false) return false;
+
+ int count = ((int (*)(id, SEL))objc_msgSend)(propertyList, sel_registerName("count"));
if (count == 0)
return 0;
u32 i;
for (i = 0; i < (u32)count; i++) {
- id fileURL = objc_msgSend_arr(fileURLs, sel_registerName("objectAtIndex:"), i);
+ id fileURL = objc_msgSend_arr(propertyList, sel_registerName("objectAtIndex:"), i);
const char *filePath = ((const char* (*)(id, SEL))objc_msgSend)(fileURL, sel_registerName("UTF8String"));
- int string_count = ((int (*)(id, SEL))objc_msgSend)(fileURL, sel_registerName("count"));
+ int string_count = ((int (*)(id, SEL))objc_msgSend)(fileURL, sel_registerName("length"));
RGFW_dataDropCallback(win, filePath, (size_t)string_count + 1, RGFW_dataFile);
}
@@ -13050,8 +14070,23 @@ static void RGFW__osxDidChangeScreenParameters(id self, SEL _cmd, id notificatio
RGFW_pollMonitors();
}
-static void RGFW__osxWindowDeminiaturize(id self, SEL sel) {
- RGFW_UNUSED(sel);
+static NSUInteger RGFW__osxApplicationShouldTerminate(id self, SEL _cmd, id sender) {
+ RGFW_UNUSED(self); RGFW_UNUSED(_cmd); RGFW_UNUSED(sender);
+
+ id windows = objc_msgSend_id(_RGFW->NSApp, sel_registerName("windows"));
+ NSUInteger count = (NSUInteger)objc_msgSend_uint(windows, sel_registerName("count"));
+
+ for (unsigned long i = 0; i < count; i++) {
+ id window = ((id (*)(id, SEL, int))objc_msgSend) (windows, sel_registerName("objectAtIndex:"), (int)i);
+ id delegate = ((id (*)(id, SEL))objc_msgSend) (window, sel_registerName("delegate"));
+ ((void(*)(id, SEL, id))objc_msgSend)(delegate, sel_registerName("windowShouldClose:"), window);
+ }
+
+ return 0; /* NSTerminateCancel */
+}
+
+static void RGFW__osxWindowDeminiaturize(id self, SEL sel, id notification) {
+ RGFW_UNUSED(sel); RGFW_UNUSED(notification);
RGFW_window* win = NULL;
object_getInstanceVariable(self, "RGFW_window", (void**)&win);
if (win == NULL) return;
@@ -13059,8 +14094,8 @@ static void RGFW__osxWindowDeminiaturize(id self, SEL sel) {
RGFW_windowRestoredCallback(win, win->x, win->y, win->w, win->h);
}
-static void RGFW__osxWindowMiniaturize(id self, SEL sel) {
- RGFW_UNUSED(sel);
+static void RGFW__osxWindowMiniaturize(id self, SEL sel, id notification) {
+ RGFW_UNUSED(sel); RGFW_UNUSED(notification);
RGFW_window* win = NULL;
object_getInstanceVariable(self, "RGFW_window", (void**)&win);
if (win == NULL) return;
@@ -13069,8 +14104,8 @@ static void RGFW__osxWindowMiniaturize(id self, SEL sel) {
}
-static void RGFW__osxWindowBecameKey(id self, SEL sel) {
- RGFW_UNUSED(sel);
+static void RGFW__osxWindowBecameKey(id self, SEL sel, id notification) {
+ RGFW_UNUSED(sel); RGFW_UNUSED(notification);
RGFW_window* win = NULL;
object_getInstanceVariable(self, "RGFW_window", (void**)&win);
if (win == NULL) return;
@@ -13078,8 +14113,8 @@ static void RGFW__osxWindowBecameKey(id self, SEL sel) {
RGFW_windowFocusCallback(win, RGFW_TRUE);
}
-static void RGFW__osxWindowResignKey(id self, SEL sel) {
- RGFW_UNUSED(sel);
+static void RGFW__osxWindowResignKey(id self, SEL sel, id notification) {
+ RGFW_UNUSED(sel); RGFW_UNUSED(notification);
RGFW_window* win = NULL;
object_getInstanceVariable(self, "RGFW_window", (void**)&win);
if (win == NULL) return;
@@ -13113,8 +14148,8 @@ static void RGFW__osxDidWindowResize(id self, SEL _cmd, id notification) {
RGFW_windowResizedCallback(win, win->w, win->h);
}
-static void RGFW__osxWindowMove(id self, SEL sel) {
- RGFW_UNUSED(sel);
+static void RGFW__osxWindowMove(id self, SEL sel, id notification) {
+ RGFW_UNUSED(sel); RGFW_UNUSED(notification);
RGFW_window* win = NULL;
object_getInstanceVariable(self, "RGFW_window", (void**)&win);
if (win == NULL) return;
@@ -13155,7 +14190,9 @@ static void RGFW__osxDrawRect(id self, SEL _cmd, CGRect rect) {
object_getInstanceVariable(self, "RGFW_window", (void**)&win);
if (win == NULL) return;
- RGFW_windowRefreshCallback(win, 0, 0, win->w, win->h);
+ float y = RGFW_cocoaYTransform((float)(rect.size.height - 1));
+
+ RGFW_windowRefreshCallback(win, (i32)rect.origin.x, (i32)y, (i32)rect.size.width, (i32)rect.size.height);
}
static void RGFW__osxMouseEntered(id self, SEL _cmd, id event) {
@@ -13267,7 +14304,7 @@ static void RGFW__osxMouseMoved(id self, SEL _cmd, id event) {
CGFloat vecX = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(event, sel_registerName("deltaX"));
CGFloat vecY = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(event, sel_registerName("deltaY"));
- RGFW_mousePosCallback(win, (i32)p.x, (i32)(win->h - p.y));
+ RGFW_mouseMotionCallback(win, (i32)p.x, (i32)(win->h - p.y));
RGFW_rawMotionCallback(win, (float)vecX, (float)vecY);
}
@@ -13315,10 +14352,27 @@ static void RGFW__osxScrollWheel(id self, SEL _cmd, id event) {
object_getInstanceVariable(self, "RGFW_window", (void**)&win);
if (win == NULL) return;
- float deltaX = (float)((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(event, sel_registerName("deltaX"));
- float deltaY = (float)((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(event, sel_registerName("deltaY"));
+ CGFloat deltaX = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(event, sel_registerName("scrollingDeltaX"));
+ CGFloat deltaY = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(event, sel_registerName("scrollingDeltaY"));
+
+ if (objc_msgSend_bool(event, sel_registerName("hasPreciseScrollingDeltas"))) {
+ deltaX *= (CGFloat)0.1;
+ deltaY *= (CGFloat)0.1;
+ }
+
+ RGFW_mouseScrollCallback(win, (float)deltaX, (float)deltaY);
+}
- RGFW_mouseScrollCallback(win, deltaX, deltaY);
+BOOL RGFW__osxCanBecomeKeyWindow(id self, SEL _cmd);
+BOOL RGFW__osxCanBecomeKeyWindow(id self, SEL _cmd) {
+ RGFW_UNUSED(self); RGFW_UNUSED(_cmd);
+ return YES;
+}
+
+BOOL RGFW__osxCanBecomeMainWindow(id self, SEL _cmd);
+BOOL RGFW__osxCanBecomeMainWindow(id self, SEL _cmd) {
+ RGFW_UNUSED(self); RGFW_UNUSED(_cmd);
+ return YES;
}
RGFW_format RGFW_nativeFormat(void) { return RGFW_formatRGBA8; }
@@ -13494,7 +14548,8 @@ void RGFW_initKeycodesPlatform(void) {
_RGFW->keycodes[0x4E] = RGFW_keyPadMinus;
}
-i32 RGFW_initPlatform(void) {
+i32 RGFW_initPlatform(const char* className, RGFW_initFlags flags) {
+ RGFW_UNUSED(className); RGFW_UNUSED(flags);
_RGFW->tisBundle = (void*)CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox"));
TISGetInputSourcePropertySrc = (PFN_TISGetInputSourceProperty)CFBundleGetFunctionPointerForName((CFBundleRef)_RGFW->tisBundle, CFSTR("TISGetInputSourceProperty"));
@@ -13503,31 +14558,42 @@ i32 RGFW_initPlatform(void) {
CFStringRef* cfStr = (CFStringRef*)CFBundleGetDataPointerForName((CFBundleRef)_RGFW->tisBundle, CFSTR("kTISPropertyUnicodeKeyLayoutData"));;
if (cfStr) kTISPropertyUnicodeKeyLayoutDataSrc = *cfStr;
-
- class_addMethod(objc_getClass("NSObject"), sel_registerName("windowShouldClose:"), (IMP)(void*)RGFW_OnClose, 0);
-
- /* NOTE(EimaMei): Fixes the 'Boop' sfx from constantly playing each time you click a key. Only a problem when running in the terminal. */
- class_addMethod(objc_getClass("NSWindowClass"), sel_registerName("acceptsFirstResponder:"), (IMP)(void*)RGFW__osxAcceptsFirstResponder, 0);
- class_addMethod(objc_getClass("NSWindowClass"), sel_registerName("performKeyEquivalent:"), (IMP)(void*)RGFW__osxPerformKeyEquivalent, 0);
-
_RGFW->NSApp = objc_msgSend_id(objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
-
- NSRetain(_RGFW->NSApp);
+ ((void (*)(id, SEL, NSUInteger))objc_msgSend) ((id)_RGFW->NSApp, sel_registerName("setActivationPolicy:"), NSApplicationActivationPolicyRegular);
+ /* Note about addMethod strings
+ * @ -> id, : -> SEL, B -> bool
+ * a basic char is a c-type, capital letter = unsigned, ^ = pointer
+ * e.g. i = int, I = unsigned int c = char, C = unsigned char and ^C = unsigned char*
+ * most functions start with v@: because it's `void function(id self, SEL _cmd)
+ */
_RGFW->customNSAppDelegateClass = objc_allocateClassPair(objc_getClass("NSObject"), "RGFWNSAppDelegate", 0);
+ if (_RGFW->customNSAppDelegateClass == NULL) {
+ RGFW_debugCallback(RGFW_typeError, RGFW_errObjcRuntime, "failed to create RGFWNSAppDelegate class");
+ return -1;
+ }
+
class_addMethod((Class)_RGFW->customNSAppDelegateClass, sel_registerName("applicationDidChangeScreenParameters:"), (IMP)RGFW__osxDidChangeScreenParameters, "v@:@");
+ class_addMethod((Class)_RGFW->customNSAppDelegateClass, sel_registerName("applicationShouldTerminate:"), (IMP)RGFW__osxApplicationShouldTerminate, "@:@");
objc_registerClassPair((Class)_RGFW->customNSAppDelegateClass);
_RGFW->customNSAppDelegate = objc_msgSend_id(NSAlloc(_RGFW->customNSAppDelegateClass), sel_registerName("init"));
objc_msgSend_void_id(_RGFW->NSApp, sel_registerName("setDelegate:"), _RGFW->customNSAppDelegate);
- ((void (*)(id, SEL, NSUInteger))objc_msgSend) ((id)_RGFW->NSApp, sel_registerName("setActivationPolicy:"), NSApplicationActivationPolicyRegular);
+ objc_msgSend_void(_RGFW->NSApp, sel_registerName("finishLaunching"));
_RGFW->customViewClasses[0] = objc_allocateClassPair(objc_getClass("NSView"), "RGFWCustomView", 0);
_RGFW->customViewClasses[1] = objc_allocateClassPair(objc_getClass("NSOpenGLView"), "RGFWOpenGLCustomView", 0);
for (size_t i = 0; i < 2; i++) {
- class_addIvar((Class)_RGFW->customViewClasses[i], "RGFW_window", sizeof(RGFW_window*), sizeof(RGFW_window*), "L");
- class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("drawRect:"), (IMP)RGFW__osxDrawRect, "v@:{CGRect=ffff}");
+ if (_RGFW->customViewClasses[i] == NULL) {
+ RGFW_debugCallback(RGFW_typeError, RGFW_errObjcRuntime, (i == 0) ? "failed to create RGFWCustomView class" : "failed to create RGFWOpenGLCustomView class");
+ return -1;
+ }
+
+ RGFW_ASSERT((sizeof(RGFW_window*) <= 8)); /* some future where pointers are greater than 8 bytes (64-bit) (I'm pretty sure much more will be broken if this is the case) */
+ class_addIvar((Class)_RGFW->customViewClasses[i], "RGFW_window", sizeof(RGFW_window*), (sizeof(RGFW_window*) == 8) ? 3 : 2, "^v");
+ class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("acceptsFirstMouse:"), (IMP)RGFW__osxAcceptsFirstMouse, "B@:@");
+ class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("drawRect:"), (IMP)RGFW__osxDrawRect, "v@:{CGRect={CGPoint=dd}{CGSize=dd}}");
class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("viewDidChangeBackingProperties"), (IMP)RGFW__osxViewDidChangeBackingProperties, "v@:");
class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("mouseDown:"), (IMP)RGFW__osxMouseDown, "v@:@");
class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("rightMouseDown:"), (IMP)RGFW__osxMouseDown, "v@:@");
@@ -13546,27 +14612,45 @@ i32 RGFW_initPlatform(void) {
class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("mouseExited:"), (IMP)RGFW__osxMouseExited, "v@:@");
class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("flagsChanged:"), (IMP)RGFW__osxFlagsChanged, "v@:@");
class_addMethod((Class)_RGFW->customViewClasses[i], sel_getUid("acceptsFirstResponder"), (IMP)RGFW__osxAcceptsFirstResponder, "B@:");
- class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("initWithRGFWWindow:"), (IMP)RGFW__osxCustomInitWithRGFWWindow, "@@:{CGRect={CGPoint=dd}{CGSize=dd}}");
+ class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("initWithRGFWWindow:"), (IMP)RGFW__osxCustomInitWithRGFWWindow, "@@:^v");
class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("wantsUpdateLayer"), (IMP)RGFW__osxWantsUpdateLayer, "B@:");
class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("updateLayer"), (IMP)RGFW__osxUpdateLayer, "v@:");
+ class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("draggingEntered:"), (IMP)RGFW__osxDraggingEntered, "L@:@");
+ class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("draggingUpdated:"), (IMP)RGFW__osxDraggingUpdated, "L@:@");
+ class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("draggingExited:"), (IMP)RGFW__osxDraggingEnded, "v@:@");
+ class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("draggingEnded:"), (IMP)RGFW__osxDraggingEnded, "v@:@");
+ class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("prepareForDragOperation:"), (IMP)RGFW__osxPrepareForDragOperation, "B@:@");
+ class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("performDragOperation:"), (IMP)RGFW__osxPerformDragOperation, "B@:@");
+ class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("performKeyEquivalent:"), (IMP)(void*)RGFW__osxPerformKeyEquivalent, "B@:@");
objc_registerClassPair((Class)_RGFW->customViewClasses[i]);
}
_RGFW->customWindowDelegateClass = objc_allocateClassPair(objc_getClass("NSObject"), "RGFWWindowDelegate", 0);
- class_addIvar((Class)_RGFW->customWindowDelegateClass, "RGFW_window", sizeof(RGFW_window*), sizeof(RGFW_window*), "L");
+ if (_RGFW->customWindowDelegateClass == NULL) {
+ RGFW_debugCallback(RGFW_typeError, RGFW_errObjcRuntime, "failed to create RGFWWindowDelegate class");
+ return -1;
+ }
+
+ class_addIvar((Class)_RGFW->customWindowDelegateClass, "RGFW_window", sizeof(RGFW_window*), (sizeof(RGFW_window*) == 8) ? 3 : 2, "^v");
class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidResize:"), (IMP)RGFW__osxDidWindowResize, "v@:@");
- class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidMove:"), (IMP) RGFW__osxWindowMove, "");
- class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidMiniaturize:"), (IMP) RGFW__osxWindowMiniaturize, "");
- class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidDeminiaturize:"), (IMP) RGFW__osxWindowDeminiaturize, "");
- class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidBecomeKey:"), (IMP) RGFW__osxWindowBecameKey, "");
- class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidResignKey:"), (IMP) RGFW__osxWindowResignKey, "");
- class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("draggingEntered:"), (IMP)RGFW__osxDraggingEntered, "l@:@");
- class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("draggingUpdated:"), (IMP)RGFW__osxDraggingUpdated, "l@:@");
- class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("draggingExited:"), (IMP)RGFW__osxDraggingEnded, "v@:@");
- class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("draggingEnded:"), (IMP)RGFW__osxDraggingEnded, "v@:@");
- class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("prepareForDragOperation:"), (IMP)RGFW__osxPrepareForDragOperation, "B@:@");
- class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("performDragOperation:"), (IMP)RGFW__osxPerformDragOperation, "B@:@");
+ class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidMove:"), (IMP) RGFW__osxWindowMove, "v@:@");
+ class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidMiniaturize:"), (IMP) RGFW__osxWindowMiniaturize, "v@:@");
+ class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidDeminiaturize:"), (IMP) RGFW__osxWindowDeminiaturize, "v@:@");
+ class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidBecomeKey:"), (IMP) RGFW__osxWindowBecameKey, "v@:@");
+ class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidResignKey:"), (IMP) RGFW__osxWindowResignKey, "v@:@");
+ class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowShouldClose:"), (IMP)(void*)RGFW_osxWindowShouldClose, "B@:@");
objc_registerClassPair((Class)_RGFW->customWindowDelegateClass);
+
+ _RGFW->customWindowClass = objc_allocateClassPair(objc_getClass("NSWindow"), "RGFWWindowClass", 0);
+ if (_RGFW->customWindowClass== NULL) {
+ RGFW_debugCallback(RGFW_typeError, RGFW_errObjcRuntime, "failed to create RGFWWindowClass class");
+ return -1;
+ }
+
+ class_addMethod((Class)_RGFW->customWindowClass, sel_registerName("canBecomeKeyWindow"), (IMP)RGFW__osxCanBecomeKeyWindow, "B@:");
+ class_addMethod((Class)_RGFW->customWindowClass, sel_registerName("canBecomeMainWindow"),(IMP)RGFW__osxCanBecomeMainWindow, "B@:");
+ objc_registerClassPair((Class)_RGFW->customWindowClass);
+
return 0;
}
@@ -13613,17 +14697,19 @@ RGFW_window* RGFW_createWindowPlatform(const char* name, RGFW_windowFlags flags,
windowRect.origin.y = (double)RGFW_cocoaYTransform((float)(win->y + win->h - 1));
windowRect.size.width = (double)win->w;
windowRect.size.height = (double)win->h;
- NSBackingStoreType macArgs = (NSBackingStoreType)(NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSBackingStoreBuffered | NSWindowStyleMaskTitled);
+ NSWindowStyleMask macArgs = (NSWindowStyleMask)(NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSBackingStoreBuffered);
if (!(flags & RGFW_windowNoResize))
- macArgs = (NSBackingStoreType)(macArgs | (NSBackingStoreType)NSWindowStyleMaskResizable);
+ macArgs |= (NSWindowStyleMask)NSWindowStyleMaskResizable;
if (!(flags & RGFW_windowNoBorder))
- macArgs = (NSBackingStoreType)(macArgs | (NSBackingStoreType)NSWindowStyleMaskTitled);
+ macArgs |= (NSWindowStyleMask)NSWindowStyleMaskTitled;
+ else
+ macArgs |= (NSWindowStyleMask)NSWindowStyleMaskBorderless;
{
- void* nsclass = objc_getClass("NSWindow");
+ void* nsclass = objc_getClass("RGFWWindowClass");
SEL func = sel_registerName("initWithContentRect:styleMask:backing:defer:");
- win->src.window = ((id(*)(id, SEL, NSRect, NSWindowStyleMask, NSBackingStoreType, bool))objc_msgSend)
+ win->src.window = ((id(*)(id, SEL, NSRect, NSWindowStyleMask, NSWindowStyleMask, bool))objc_msgSend)
(NSAlloc(nsclass), func, windowRect, (NSWindowStyleMask)macArgs, macArgs, false);
}
@@ -13635,13 +14721,6 @@ RGFW_window* RGFW_createWindowPlatform(const char* name, RGFW_windowFlags flags,
objc_msgSend_void_id((id)win->src.window, sel_registerName("setDelegate:"), (id)win->src.delegate);
- if (flags & RGFW_windowAllowDND) {
- win->internal.flags |= RGFW_windowAllowDND;
-
- NSPasteboardType types[] = {NSPasteboardTypeURL, NSPasteboardTypeFileURL, NSPasteboardTypeString};
- NSregisterForDraggedTypes((id)win->src.window, types, 3);
- }
-
objc_msgSend_void_bool((id)win->src.window, sel_registerName("setAcceptsMouseMovedEvents:"), true);
if (flags & RGFW_windowTransparent) {
@@ -13651,46 +14730,38 @@ RGFW_window* RGFW_createWindowPlatform(const char* name, RGFW_windowFlags flags,
NSColor_colorWithSRGB(0, 0, 0, 0));
}
- /* Show the window */
- objc_msgSend_void_bool((id)_RGFW->NSApp, sel_registerName("activateIgnoringOtherApps:"), true);
+ if (flags & RGFW_windowAllowDND) {
+ win->internal.flags |= RGFW_windowAllowDND;
+ }
if (_RGFW->root == NULL) {
objc_msgSend_void(win->src.window, sel_registerName("makeMainWindow"));
}
- objc_msgSend_void(win->src.window, sel_registerName("makeKeyWindow"));
-
- NSRetain(win->src.window);
-
win->src.view = ((id(*)(id, SEL, RGFW_window*))objc_msgSend) (NSAlloc((Class)_RGFW->customViewClasses[0]), sel_registerName("initWithRGFWWindow:"), win);
+
+ RGFW_cocoaFetchRect(win);
return win;
}
void RGFW_window_setBorder(RGFW_window* win, RGFW_bool border) {
- NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.window, sel_registerName("frame"));
- NSRect content = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.view, sel_registerName("frame"));
- double offset = 0;
-
RGFW_setBit(&win->internal.flags, RGFW_windowNoBorder, !border);
- NSBackingStoreType storeType = (NSBackingStoreType)(NSWindowStyleMaskBorderless | NSWindowStyleMaskFullSizeContentView);
- if (border)
- storeType = (NSBackingStoreType)(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable);
- if (!(win->internal.flags & RGFW_windowNoResize)) {
- storeType = (NSBackingStoreType)(storeType | (NSBackingStoreType)NSWindowStyleMaskResizable);
- }
- ((void (*)(id, SEL, NSBackingStoreType))objc_msgSend)((id)win->src.window, sel_registerName("setStyleMask:"), storeType);
+ NSWindowStyleMask styleMask = ((NSWindowStyleMask (*)(id, SEL))objc_msgSend)((id)win->src.window, sel_registerName("styleMask"));
+ if (border) {
+ styleMask |= (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
+ styleMask &= (u32)~NSWindowStyleMaskBorderless;
+ } else {
+ styleMask |= NSWindowStyleMaskBorderless;
+ styleMask &= (u32)~(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
+ }
- if (!border) {
- id miniaturizeButton = objc_msgSend_int((id)win->src.window, sel_registerName("standardWindowButton:"), NSWindowMiniaturizeButton);
- id titleBarView = objc_msgSend_id(miniaturizeButton, sel_registerName("superview"));
- objc_msgSend_void_bool(titleBarView, sel_registerName("setHidden:"), true);
+ ((void (*)(id, SEL, NSWindowStyleMask))objc_msgSend)((id)win->src.window, sel_registerName("setStyleMask:"), styleMask);
- offset = (double)(frame.size.height - content.size.height);
- }
+ /* changing the style can clear the first responder */
+ ((void (*)(id, SEL, id))objc_msgSend)((id)win->src.window, sel_registerName("makeFirstResponder:"), (id)win->src.view);
- RGFW_window_resize(win, win->w, win->h + (i32)offset);
- win->h -= (i32)offset;
+ RGFW_window_move(win, win->x, win->y);
}
RGFW_bool RGFW_getGlobalMouse(i32* x, i32* y) {
@@ -13723,8 +14794,12 @@ void RGFW_waitForEvent(i32 waitMS) {
id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
eventPool = objc_msgSend_id(eventPool, sel_registerName("init"));
- void* date = (void*) ((id(*)(Class, SEL, double))objc_msgSend)
- (objc_getClass("NSDate"), sel_registerName("dateWithTimeIntervalSinceNow:"), waitMS);
+ void* date = objc_msgSend_class(objc_getClass("NSDate"), sel_registerName("distantFuture"));
+ if (waitMS >= 0) {
+ double seconds = (((double)waitMS) / ((double)1000));
+ date = (void*) ((id(*)(Class, SEL, double))objc_msgSend)
+ (objc_getClass("NSDate"), sel_registerName("dateWithTimeIntervalSinceNow:"), seconds);
+ }
SEL eventFunc = sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:");
id e = (id) ((id(*)(id, SEL, NSEventMask, void*, id, bool))objc_msgSend)
@@ -13734,6 +14809,15 @@ void RGFW_waitForEvent(i32 waitMS) {
if (e) {
((void (*)(id, SEL, id, bool))objc_msgSend)
((id)_RGFW->NSApp, sel_registerName("postEvent:atStart:"), e, 1);
+
+ u32 flags = (u32)((u32(*)(id, SEL))objc_msgSend)((id)e, sel_registerName("modifierFlags"));
+ if (flags & NSEventModifierFlagCommand) {
+ id window = objc_msgSend_id(_RGFW->NSApp, sel_registerName("keyWindow"));
+
+ if (window) {
+ objc_msgSend_void_id((id)window, sel_registerName("sendEvent:"), e);
+ }
+ }
}
objc_msgSend_bool_void(eventPool, sel_registerName("drain"));
@@ -13801,31 +14885,23 @@ void RGFW_pollEvents(void) {
}
-void RGFW_window_move(RGFW_window* win, i32 x, i32 y) {
- RGFW_ASSERT(win != NULL);
-
+void RGFW_window_movePlatform(RGFW_window* win, i32 x, i32 y) {
NSRect content = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.view, sel_registerName("frame"));
-
- win->x = x;
- win->y = (i32)RGFW_cocoaYTransform((float)y + (float)content.size.height - 1.0f);
-
- ((void(*)(id,SEL,NSPoint))objc_msgSend)((id)win->src.window, sel_registerName("setFrameOrigin:"), (NSPoint){(double)x, (double)y});
+ float yFlip = RGFW_cocoaYTransform((float)y + (float)content.size.height - 1.0f);
+ ((void(*)(id,SEL,NSPoint))objc_msgSend)((id)win->src.window, sel_registerName("setFrameOrigin:"), (NSPoint){(double)x, (double)yFlip});
+ RGFW_cocoaFetchRect(win);
}
-void RGFW_window_resize(RGFW_window* win, i32 w, i32 h) {
- RGFW_ASSERT(win != NULL);
-
+void RGFW_window_resizePlatform(RGFW_window* win, i32 w, i32 h) {
NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.window, sel_registerName("frame"));
- NSRect content = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.view, sel_registerName("frame"));
- float offset = (float)(frame.size.height - content.size.height);
-
- win->w = w;
- win->h = h;
+ NSRect content = ((NSRect(*)(id, SEL, NSRect))abi_objc_msgSend_stret)((id)win->src.window, sel_registerName("contentRectForFrameRect:"), frame);
+ content.origin.y += content.size.height - (CGFloat)h;
+ content.size = (CGSize){(CGFloat)w, (CGFloat)h};
+ frame = ((NSRect(*)(id, SEL, NSRect))abi_objc_msgSend_stret)((id)win->src.window, sel_registerName("frameRectForContentRect:"), content);
- ((void(*)(id, SEL, CGRect))objc_msgSend)((id)win->src.view, sel_registerName("setFrame:"), (NSRect){{0, 0}, {(double)win->w, (double)win->h}});
- ((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend)
- ((id)win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{(double)win->x, (double)win->y}, {(double)win->w, (double)win->h + (double)offset}}, true, true);
+ ((void(*)(id, SEL, CGRect))objc_msgSend)((id)win->src.view, sel_registerName("setFrame:"),frame);
+ RGFW_cocoaFetchRect(win);
}
void RGFW_window_focus(RGFW_window* win) {
@@ -13837,76 +14913,43 @@ void RGFW_window_focus(RGFW_window* win) {
void RGFW_window_raise(RGFW_window* win) {
RGFW_ASSERT(win != NULL);
((id(*)(id, SEL, SEL))objc_msgSend)((id)win->src.window, sel_registerName("orderFront:"), (SEL)NULL);
- objc_msgSend_void_id(win->src.window, sel_registerName("setLevel:"), kCGNormalWindowLevelKey);
}
-void RGFW_window_setFullscreen(RGFW_window* win, RGFW_bool fullscreen) {
- RGFW_ASSERT(win != NULL);
- if (fullscreen && (win->internal.flags & RGFW_windowFullscreen)) return;
- if (!fullscreen && !(win->internal.flags & RGFW_windowFullscreen)) return;
-
+void RGFW_window_setFullscreenPlatform(RGFW_window* win, RGFW_bool fullscreen) {
if (fullscreen) {
- win->internal.oldX = win->x;
- win->internal.oldY = win->y;
- win->internal.oldW = win->w;
- win->internal.oldH = win->h;
-
- win->internal.flags |= RGFW_windowFullscreen;
-
- RGFW_monitor* mon = RGFW_window_getMonitor(win);
- RGFW_monitor_scaleToWindow(mon, win);
-
- RGFW_window_setBorder(win, RGFW_FALSE);
-
- if (mon != NULL) {
- win->x = mon->x;
- win->y = mon->y;
- win->w = mon->mode.w;
- win->h = mon->mode.h;
- RGFW_window_resize(win, mon->mode.w, mon->mode.h);
- RGFW_window_move(win, mon->x, mon->y);
- }
-
((id(*)(id, SEL, SEL))objc_msgSend)((id)win->src.window, sel_registerName("orderFront:"), (SEL)NULL);
objc_msgSend_void_id(win->src.window, sel_registerName("setLevel:"), 25);
+ } else {
+ objc_msgSend_void_id(win->src.window, sel_registerName("setLevel:"), kCGNormalWindowLevel);
}
- objc_msgSend_void_SEL(win->src.window, sel_registerName("toggleFullScreen:"), NULL);
+ NSWindowStyleMask styleMask = ((NSWindowStyleMask (*)(id, SEL))objc_msgSend)((id)win->src.window, sel_registerName("styleMask"));
- if (!fullscreen) {
- win->x = win->internal.oldX;
- win->y = win->internal.oldY;
- win->w = win->internal.oldW;
- win->h = win->internal.oldH;
- win->internal.flags &= ~(u32)RGFW_windowFullscreen;
-
- RGFW_window_resize(win, win->w, win->h);
- RGFW_window_move(win, win->x, win->y);
+ if (RGFW_BOOL(styleMask & NSWindowStyleMaskFullScreen) != fullscreen) {
+ objc_msgSend_void_SEL(win->src.window, sel_registerName("toggleFullScreen:"), NULL);
}
}
-void RGFW_window_maximize(RGFW_window* win) {
- RGFW_ASSERT(win != NULL);
+void RGFW_window_maximizePlatform(RGFW_window* win) {
if (RGFW_window_isMaximized(win)) return;
- win->internal.flags |= RGFW_windowMaximize;
objc_msgSend_void_SEL(win->src.window, sel_registerName("zoom:"), NULL);
- RGFW_window_fetchSize(win, NULL, NULL);
}
-void RGFW_window_minimize(RGFW_window* win) {
+void RGFW_window_minimizePlatform(RGFW_window* win) {
RGFW_ASSERT(win != NULL);
- objc_msgSend_void_SEL(win->src.window, sel_registerName("performMiniaturize:"), NULL);
+ objc_msgSend_void_SEL(win->src.window, sel_registerName("miniaturize:"), NULL);
}
void RGFW_window_setFloating(RGFW_window* win, RGFW_bool floating) {
RGFW_ASSERT(win != NULL);
- if (floating) objc_msgSend_void_id(win->src.window, sel_registerName("setLevel:"), kCGFloatingWindowLevelKey);
- else objc_msgSend_void_id(win->src.window, sel_registerName("setLevel:"), kCGNormalWindowLevelKey);
+ if (floating) objc_msgSend_void_id(win->src.window, sel_registerName("setLevel:"), kCGFloatingWindowLevel);
+ else objc_msgSend_void_id(win->src.window, sel_registerName("setLevel:"), kCGNormalWindowLevel);
}
void RGFW_window_setOpacity(RGFW_window* win, u8 opacity) {
- objc_msgSend_int(win->src.window, sel_registerName("setAlphaValue:"), opacity);
+ ((void(*)(id, SEL, CGFloat))objc_msgSend) ((id)win->src.window, sel_registerName("setAlphaValue:"), ((CGFloat)opacity) / (CGFloat)255.0);
+
objc_msgSend_void_bool(win->src.window, sel_registerName("setOpaque:"), (opacity < (u8)255));
if (opacity)
@@ -13914,7 +14957,7 @@ void RGFW_window_setOpacity(RGFW_window* win, u8 opacity) {
}
-void RGFW_window_restore(RGFW_window* win) {
+void RGFW_window_restorePlatform(RGFW_window* win) {
RGFW_ASSERT(win != NULL);
if (RGFW_window_isMaximized(win))
@@ -13927,7 +14970,7 @@ void RGFW_window_restore(RGFW_window* win) {
RGFW_bool RGFW_window_isFloating(RGFW_window* win) {
RGFW_ASSERT(win != NULL);
int level = ((int (*)(id, SEL))objc_msgSend) ((id)(win->src.window), (SEL)sel_registerName("level"));
- return level > kCGNormalWindowLevelKey;
+ return level > kCGNormalWindowLevel;
}
void RGFW_window_setName(RGFW_window* win, const char* name) {
@@ -14003,7 +15046,7 @@ id NSCursor_arrowStr(const char* str) {
void* nclass = objc_getClass("NSCursor");
SEL func = sel_registerName(str);
id mouse = (id) objc_msgSend_id(nclass, func);
- NSRetain(mouse);
+ objc_msgSend_void((id)mouse, sel_registerName("retain"));
return mouse;
}
@@ -14078,7 +15121,9 @@ void RGFW_freeMouse(RGFW_mouse* mouse) {
}
void RGFW_window_showMouse(RGFW_window* win, RGFW_bool show) {
+ if (RGFW_window_isMouseHidden(win) != show) return;
RGFW_window_showMouseFlags(win, show);
+
if (show) CGDisplayShowCursor(kCGDirectMainDisplay);
else CGDisplayHideCursor(kCGDirectMainDisplay);
}
@@ -14105,12 +15150,13 @@ void RGFW_window_hide(RGFW_window* win) {
objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), false);
}
-void RGFW_window_show(RGFW_window* win) {
+void RGFW_window_showPlatform(RGFW_window* win) {
if (win->internal.flags & RGFW_windowFocusOnShow)
((id(*)(id, SEL, SEL))objc_msgSend)((id)win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL);
((id(*)(id, SEL, SEL))objc_msgSend)((id)win->src.window, sel_registerName("orderFront:"), NULL);
objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true);
+ RGFW_cocoaFetchRect(win);
}
void RGFW_window_flash(RGFW_window* win, RGFW_flashRequest request) {
@@ -14196,14 +15242,17 @@ float RGFW_osx_getRefreshRate(CGDirectDisplayID display, CGDisplayModeRef mode)
}
void RGFW_pollMonitors(void) {
- static CGDirectDisplayID displays[RGFW_MAX_MONITORS];
u32 count;
- if (CGGetActiveDisplayList(RGFW_MAX_MONITORS, displays, &count) != kCGErrorSuccess) {
+ if (CGGetActiveDisplayList(0, NULL, &count) != kCGErrorSuccess) {
+ return;
+ }
+
+ CGDirectDisplayID* displays = (CGDirectDisplayID*)RGFW_ALLOC(sizeof(CGDirectDisplayID) * count);
+ if (CGGetActiveDisplayList(count, displays, &count) != kCGErrorSuccess) {
return;
}
- if (count > RGFW_MAX_MONITORS) count = RGFW_MAX_MONITORS;
for (RGFW_monitorNode* node = _RGFW->monitors.list.head; node; node = node->next) {
node->disconnected = RGFW_TRUE;
@@ -14223,27 +15272,29 @@ void RGFW_pollMonitors(void) {
if (node->uintNum == uintNum) break;
}
- if (node) {
- node->screen = (void*)screen;
- node->display = displays[i];
- node->disconnected = RGFW_FALSE;
- if (displays[i] == primary) {
- _RGFW->monitors.primary = node;
- }
- continue;
- }
-
const char name[] = "MacOS\0";
RGFW_MEMCPY(monitor.name, name, 6);
CGRect bounds = CGDisplayBounds(displays[i]);
monitor.x = (i32)bounds.origin.x;
- monitor.y = (i32)RGFW_cocoaYTransform((float)(bounds.origin.y + bounds.size.height - 1));
+ monitor.y = (i32)bounds.origin.y;
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displays[i]);
+
+ CFArrayRef allModes = CGDisplayCopyAllDisplayModes(displays[i], NULL);
+ CFIndex modeCount = (CFIndex)CFArrayGetCount(allModes);
+
+ CFIndex modeIndex;
+ for (modeIndex = 0; modeIndex < modeCount && allModes; modeIndex++) {
+ CGDisplayModeRef cmode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, modeIndex);
+ if (cmode == mode) {
+ monitor.mode.src = (void*)modeIndex;
+ break;
+ }
+ }
+
monitor.mode.w = (i32)CGDisplayModeGetWidth(mode);
monitor.mode.h = (i32)CGDisplayModeGetHeight(mode);
- monitor.mode.src = (void*)mode;
monitor.mode.red = 8; monitor.mode.green = 8; monitor.mode.blue = 8;
monitor.mode.refreshRate = RGFW_osx_getRefreshRate(displays[i], mode);
@@ -14262,23 +15313,42 @@ void RGFW_pollMonitors(void) {
monitor.scaleX = ((((float) (ppi_width) / dpi) * 10.0f)) / 10.0f;
monitor.scaleY = ((((float) (ppi_height) / dpi) * 10.0f)) / 10.0f;
- node = RGFW_monitors_add(&monitor);
+ if (node) {
+ node->screen = (void*)screen;
+ node->display = displays[i];
+ node->disconnected = RGFW_FALSE;
+ if (displays[i] == primary) {
+ _RGFW->monitors.primary = node;
+ }
+ continue;
+ } else {
+ node = RGFW_monitors_add(&monitor);
- node->screen = (void*)screen;
- node->uintNum = uintNum;
- node->display = displays[i];
+ node->allModes = allModes;
+ node->screen = (void*)screen;
+ node->uintNum = uintNum;
+ node->display = displays[i];
- if (displays[i] == primary) {
- _RGFW->monitors.primary = node;
- }
+ if (displays[i] == primary) {
+ _RGFW->monitors.primary = node;
+ }
- RGFW_monitorCallback(_RGFW->root, &node->mon, RGFW_TRUE);
+ RGFW_monitorCallback(_RGFW->root, &node->mon, RGFW_TRUE);
+ }
}
+ RGFW_FREE(displays);
+
RGFW_monitors_refresh();
}
+void RGFW_monitorNode_free(RGFW_monitorNode* node) {
+ RGFW_ASSERT(node);
+ CFRelease(node->allModes);
+}
+
RGFW_bool RGFW_monitor_getWorkarea(RGFW_monitor* monitor, i32* x, i32* y, i32* width, i32* height) {
+ RGFW_ASSERT(monitor != NULL);
NSRect frameRect = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)monitor->node->screen, sel_registerName("visibleFrame"));
if (x) *x = (i32)frameRect.origin.x;
@@ -14290,6 +15360,7 @@ RGFW_bool RGFW_monitor_getWorkarea(RGFW_monitor* monitor, i32* x, i32* y, i32* w
}
size_t RGFW_monitor_getGammaRampPtr(RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
+ RGFW_ASSERT(monitor != NULL);
id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
pool = objc_msgSend_id(pool, sel_registerName("init"));
@@ -14311,6 +15382,7 @@ size_t RGFW_monitor_getGammaRampPtr(RGFW_monitor* monitor, RGFW_gammaRamp* ramp)
}
RGFW_bool RGFW_monitor_setGammaRamp(RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
+ RGFW_ASSERT(monitor != NULL);
id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
pool = objc_msgSend_id(pool, sel_registerName("init"));
@@ -14332,8 +15404,9 @@ RGFW_bool RGFW_monitor_setGammaRamp(RGFW_monitor* monitor, RGFW_gammaRamp* ramp)
}
size_t RGFW_monitor_getModesPtr(RGFW_monitor* mon, RGFW_monitorMode** modes) {
+ RGFW_ASSERT(mon != NULL);
CGDirectDisplayID display = mon->node->display;
- CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, NULL);
+ CFArrayRef allModes = mon->node->allModes;
if (allModes == NULL) {
return RGFW_FALSE;
@@ -14350,16 +15423,19 @@ size_t RGFW_monitor_getModesPtr(RGFW_monitor* mon, RGFW_monitorMode** modes) {
foundMode.h = (i32)CGDisplayModeGetHeight(cmode);
foundMode.refreshRate = RGFW_osx_getRefreshRate(display, cmode);
foundMode.red = 8; foundMode.green = 8; foundMode.blue = 8;
- foundMode.src = (void*)cmode;
+ foundMode.src = (void*)i;
(*modes)[i] = foundMode;
}
- CFRelease(allModes);
return count;
}
RGFW_bool RGFW_monitor_setMode(RGFW_monitor* mon, RGFW_monitorMode* mode) {
- if (CGDisplaySetDisplayMode(mon->node->display, (CGDisplayModeRef)mode->src, NULL) == kCGErrorSuccess) {
+ RGFW_ASSERT(mon != NULL);
+
+ CGDisplayModeRef cmode = (CGDisplayModeRef)CFArrayGetValueAtIndex(mon->node->allModes, (CFIndex)mode->src);
+ if (CGDisplaySetDisplayMode(mon->node->display, cmode, NULL) == kCGErrorSuccess) {
+ mon->mode = *mode;
return RGFW_TRUE;
}
@@ -14367,8 +15443,9 @@ RGFW_bool RGFW_monitor_setMode(RGFW_monitor* mon, RGFW_monitorMode* mode) {
}
RGFW_bool RGFW_monitor_requestMode(RGFW_monitor* mon, RGFW_monitorMode* mode, RGFW_modeRequest request) {
+ RGFW_ASSERT(mon != NULL);
CGDirectDisplayID display = mon->node->display;
- CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, NULL);
+ CFArrayRef allModes = mon->node->allModes;
if (allModes == NULL) {
return RGFW_FALSE;
@@ -14385,7 +15462,7 @@ RGFW_bool RGFW_monitor_requestMode(RGFW_monitor* mon, RGFW_monitorMode* mode, RG
foundMode.h = (i32)CGDisplayModeGetHeight(cmode);
foundMode.refreshRate = RGFW_osx_getRefreshRate(display, cmode);
foundMode.red = 8; foundMode.green = 8; foundMode.blue = 8;
- foundMode.src = (void*)cmode;
+ foundMode.src = (void*)i;
if (RGFW_monitorModeCompare(mode, &foundMode, request)) {
native = cmode;
@@ -14394,8 +15471,6 @@ RGFW_bool RGFW_monitor_requestMode(RGFW_monitor* mon, RGFW_monitorMode* mode, RG
}
}
- CFRelease(allModes);
-
if (native) {
if (CGDisplaySetDisplayMode(display, native, NULL) == kCGErrorSuccess) {
return RGFW_TRUE;
@@ -14428,35 +15503,60 @@ RGFW_monitor* RGFW_window_getMonitor(RGFW_window* win) {
return &node->mon;
}
-RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity) {
- size_t clip_len;
- char* clip = (char*)NSPasteboard_stringForType(NSPasteboard_generalPasteboard(), NSPasteboardTypeString, &clip_len);
- if (clip == NULL) return -1;
+RGFW_bool RGFW_readClipboardPtr(RGFW_dataTransferType requestedType, u8* buffer, size_t capacity, RGFW_dataTransfer* data) {
+ RGFW_ASSERT(data != NULL);
- if (str != NULL) {
- if (strCapacity < clip_len)
- return 0;
+ if (requestedType != RGFW_dataText) return RGFW_FALSE;
- RGFW_MEMCPY(str, clip, clip_len);
+ size_t length = 0;
+ char* clip = (char*)NSPasteboard_stringForType(NSPasteboard_generalPasteboard(), RSGL_NSPasteboardTypeString, &length);
+ if (clip == NULL) return RGFW_FALSE;
- str[clip_len] = '\0';
- }
+ data->type = RGFW_dataText;
+ data->length = length;
- return (RGFW_ssize_t)clip_len;
+ if (clip[data->length - 1] != '\0') data->length += 1;
+
+ if (buffer == NULL) return RGFW_TRUE;
+ if (capacity < data->length) return RGFW_FALSE;
+
+ RGFW_MEMCPY(buffer, clip, length);
+ buffer[data->length - 1] = '\0';
+ data->data = (const char*)buffer;
+
+ return RGFW_TRUE;
}
-void RGFW_writeClipboard(const char* text, u32 textLen) {
- RGFW_UNUSED(textLen);
+RGFW_bool RGFW_writeClipboard(const RGFW_dataTransfer* data) {
+ RGFW_ASSERT(data != NULL);
- NSPasteboardType array[] = { NSPasteboardTypeString, NULL };
+ const char* array[] = { RSGL_NSPasteboardTypeString, NULL };
NSPasteBoard_declareTypes(NSPasteboard_generalPasteboard(), array, 1, NULL);
SEL func = sel_registerName("setString:forType:");
- ((bool (*)(id, SEL, id, id))objc_msgSend)
- (NSPasteboard_generalPasteboard(), func, NSString_stringWithUTF8String(text), NSString_stringWithUTF8String((const char*)NSPasteboardTypeString));
+ bool ret = ((bool (*)(id, SEL, id, id))objc_msgSend)
+ (NSPasteboard_generalPasteboard(), func, NSString_stringWithUTF8String(data->data), NSString_stringWithUTF8String((const char*)RSGL_NSPasteboardTypeString));
+
+ return (ret == true) ? RGFW_TRUE : RGFW_FALSE;
}
#ifdef RGFW_OPENGL
+RGFW_bool RGFW_loadGL(void) {
+ _RGFW->nativeGL_handle = (void*)CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
+ _RGFW->glGetProcAddress = RGFW_getProcAddress_OpenGL;
+ return RGFW_TRUE;
+}
+
+void RGFW_copyContext_OSX_OpenGL(RGFW_glContext* ctx, RGFW_glContext* newCtx) {
+ id pixelFormat = (id)objc_msgSend_id((id)ctx->ctx, sel_registerName("pixelFormat"));
+ id newContext = ((id (*)(id, SEL, id, id))objc_msgSend)(NSAlloc((id)objc_getClass("NSOpenGLContext")),
+ sel_registerName("initWithFormat:shareContext:"),
+ pixelFormat, (id)ctx->ctx
+ );
+
+ newCtx->ctx = newContext;
+}
+
void NSOpenGLContext_setValues(id context, const int* vals, NSOpenGLContextParameter param);
void NSOpenGLContext_setValues(id context, const int* vals, NSOpenGLContextParameter param) {
((void (*)(id, SEL, const int*, NSOpenGLContextParameter))objc_msgSend)
@@ -14468,23 +15568,16 @@ void NSOpenGLContext_setValues(id context, const int* vals, NSOpenGLContextParam
RGFW_bool RGFW_extensionSupportedPlatform_OpenGL(const char * extension, size_t len) { RGFW_UNUSED(extension); RGFW_UNUSED(len); return RGFW_FALSE; }
RGFW_proc RGFW_getProcAddress_OpenGL(const char* procname) {
- static CFBundleRef RGFWnsglFramework = NULL;
- if (RGFWnsglFramework == NULL)
- RGFWnsglFramework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
-
CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault, procname, kCFStringEncodingASCII);
- RGFW_proc symbol = (RGFW_proc)CFBundleGetFunctionPointerForName(RGFWnsglFramework, symbolName);
+ RGFW_proc symbol = (RGFW_proc)CFBundleGetFunctionPointerForName((CFBundleRef)_RGFW->nativeGL_handle, symbolName);
CFRelease(symbolName);
return symbol;
}
-RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx, RGFW_glHints* hints) {
- win->src.ctx.native = ctx;
- win->src.gfxType = RGFW_gfxNativeOpenGL;
-
+RGFW_bool RGFW_createContextPtr_OpenGL(RGFW_glContext* ctx, RGFW_glHints* hints) {
i32 attribs[40];
size_t render_type_index = 0;
{
@@ -14553,48 +15646,65 @@ RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext*
/* the pixel format can be passed directly to OpenGL context creation to create a context
this is because the format also includes information about the OpenGL version (which may be a bad thing) */
- if (win->src.view)
- NSRelease(win->src.view);
- win->src.view = (id) ((id(*)(id, SEL, NSRect, u32*))objc_msgSend) (NSAlloc(_RGFW->customViewClasses[1]),
- sel_registerName("initWithFrame:pixelFormat:"), (NSRect){{0, 0}, {(double)win->w, (double)win->h}}, (u32*)format);
-
id share = NULL;
if (hints->share) {
share = (id)hints->share->ctx;
}
- win->src.ctx.native->ctx = ((id (*)(id, SEL, id, id))objc_msgSend)(NSAlloc(objc_getClass("NSOpenGLContext")),
+ ctx->ctx = ((id (*)(id, SEL, id, id))objc_msgSend)(NSAlloc(objc_getClass("NSOpenGLContext")),
sel_registerName("initWithFormat:shareContext:"),
(id)format, share);
- win->src.ctx.native->format = format;
+ ctx->format = format;
- objc_msgSend_void_id(win->src.view, sel_registerName("setOpenGLContext:"), win->src.ctx.native->ctx);
- if (win->internal.flags & RGFW_windowTransparent) {
+ if (hints->depth == 32) {
i32 opacity = 0;
#define NSOpenGLCPSurfaceOpacity 236
- NSOpenGLContext_setValues((id)win->src.ctx.native->ctx, &opacity, (NSOpenGLContextParameter)NSOpenGLCPSurfaceOpacity);
+ NSOpenGLContext_setValues((id)ctx->ctx, &opacity, (NSOpenGLContextParameter)NSOpenGLCPSurfaceOpacity);
+ }
+
+ RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context initalized.");
+ return RGFW_TRUE;
+}
+
+RGFW_bool RGFW_window_setContext_OpenGL(RGFW_window* win, RGFW_glContext* ctx) {
+ RGFW_ASSERT(win);
+ if (ctx == NULL && win->src.ctx.native != NULL) {
+ win->src.ctx.native = NULL;
+ RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL surface freed.");
+ return RGFW_TRUE;
}
- objc_msgSend_void(win->src.ctx.native->ctx, sel_registerName("makeCurrentContext"));
+ win->src.ctx.native = ctx;
+ win->src.gfxType = RGFW_gfxNativeOpenGL;
+
+ if (win->src.view)
+ NSRelease(win->src.view);
+ win->src.view = (id) ((id(*)(id, SEL, NSRect, u32*))objc_msgSend) (NSAlloc(_RGFW->customViewClasses[1]),
+ sel_registerName("initWithFrame:pixelFormat:"), (NSRect){{0, 0}, {(double)win->w, (double)win->h}}, (u32*)ctx->format);
+
+
+ objc_msgSend_void_id(win->src.view, sel_registerName("setOpenGLContext:"), ctx->ctx);
+
+ objc_msgSend_void(ctx->ctx, sel_registerName("makeCurrentContext"));
objc_msgSend_void_id((id)win->src.window, sel_registerName("setContentView:"), win->src.view);
objc_msgSend_void_bool(win->src.view, sel_registerName("setWantsLayer:"), true);
objc_msgSend_int((id)win->src.view, sel_registerName("setLayerContentsPlacement:"), 4);
- RGFW_window_swapInterval_OpenGL(win, 0);
+ /*NOTE: another OpenGL/setFlags related hack, this because OSX the 'view' class must be setup after the NSOpenGL view is made AND after setFlags happens */
+ RGFW_osx_initView(win);
+ ((void (*)(id, SEL, id))objc_msgSend)((id)win->src.window, sel_registerName("makeFirstResponder:"), (id)win->src.view);
- RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context initalized.");
+ RGFW_window_swapInterval_OpenGL(win, 0);
+ RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL surface initalized.");
return RGFW_TRUE;
}
-void RGFW_window_deleteContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx) {
+void RGFW_deleteContextPtr_OpenGL(RGFW_glContext* ctx) {
objc_msgSend_void(ctx->format, sel_registerName("release"));
- win->src.ctx.native->format = NULL;
-
objc_msgSend_void(ctx->ctx, sel_registerName("release"));
- win->src.ctx.native->ctx = NULL;
RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context freed.");
}
@@ -14609,6 +15719,12 @@ void* RGFW_getCurrentContext_OpenGL(void) {
return objc_msgSend_id(objc_getClass("NSOpenGLContext"), sel_registerName("currentContext"));
}
+void* RGFW_getCurrentSurface_OpenGL(void) {
+ id ctx = (id)RGFW_getCurrentContext_OpenGL();
+ if (ctx == NULL) return NULL;
+ return objc_msgSend_id(ctx, sel_registerName("view"));
+}
+
void RGFW_window_swapBuffers_OpenGL(RGFW_window* win) {
RGFW_ASSERT(win && win->src.ctx.native);
objc_msgSend_void(win->src.ctx.native->ctx, sel_registerName("flushBuffer"));
@@ -14620,29 +15736,54 @@ void RGFW_window_swapInterval_OpenGL(RGFW_window* win, i32 swapInterval) {
#endif
void RGFW_deinitPlatform(void) {
- objc_msgSend_void_id(_RGFW->NSApp, sel_registerName("setDelegate:"), NULL);
+ if (_RGFW->NSApp) {
+ objc_msgSend_void_id(_RGFW->NSApp, sel_registerName("setDelegate:"), NULL);
+ NSRelease(_RGFW->customNSAppDelegate);
+ _RGFW->customNSAppDelegate = NULL;
- objc_msgSend_void_id(_RGFW->NSApp, sel_registerName("stop:"), NULL);
- NSRelease(_RGFW->NSApp);
- _RGFW->NSApp = NULL;
+ objc_msgSend_void_id(_RGFW->NSApp, sel_registerName("stop:"), NULL);
+ _RGFW->NSApp = NULL;
+ }
- NSRelease(_RGFW->customNSAppDelegate);
+ if (_RGFW->customNSAppDelegate != NULL)
+ NSRelease(_RGFW->customNSAppDelegate);
_RGFW->customNSAppDelegate = NULL;
- objc_disposeClassPair((Class)_RGFW->customViewClasses[0]);
- objc_disposeClassPair((Class)_RGFW->customViewClasses[1]);
- objc_disposeClassPair((Class)_RGFW->customWindowDelegateClass);
- objc_disposeClassPair((Class)_RGFW->customNSAppDelegateClass);
+ if (_RGFW->customViewClasses[0] != NULL)
+ objc_disposeClassPair((Class)_RGFW->customViewClasses[0]);
+ if (_RGFW->customViewClasses[0] != NULL)
+ objc_disposeClassPair((Class)_RGFW->customViewClasses[1]);
+
+ if (_RGFW->customWindowDelegateClass)
+ objc_disposeClassPair((Class)_RGFW->customWindowDelegateClass);
+
+ if (_RGFW->customWindowClass) {
+ Class kvoClass = objc_getClass("NSKVONotifying_RGFWWindowClass");
+ if (kvoClass) {
+ objc_disposeClassPair(kvoClass);
+
+ }
+ objc_disposeClassPair((Class)_RGFW->customWindowClass);
+ }
+
+ if (_RGFW->customNSAppDelegateClass)
+ objc_disposeClassPair((Class)_RGFW->customNSAppDelegateClass);
}
void RGFW_window_closePlatform(RGFW_window* win) {
+ id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
+ pool = objc_msgSend_id(pool, sel_registerName("init"));
+
objc_msgSend_void_id((id)win->src.window, sel_registerName("setDelegate:"), NULL);
NSRelease((id)win->src.delegate);
NSRelease(win->src.view);
objc_msgSend_id(win->src.window, sel_registerName("close"));
NSRelease(win->src.window);
+
+ objc_msgSend_bool_void(pool, sel_registerName("drain"));
+ RGFW_pollEvents();
}
#ifdef RGFW_VULKAN
@@ -14667,7 +15808,7 @@ VkResult RGFW_window_createSurface_Vulkan(RGFW_window* win, VkInstance instance,
if (metalLayer == NULL) {
return -1;
}
- ((void (*)(id, SEL, id))objc_msgSend)((id)nsView, sel_registerName("setLayer:"), metalLayer);
+ ((void (*)(id, SEL, id))objc_msgSend)((id)nsView, sel_registerName("setLayer:"), (id)metalLayer);
((void (*)(id, SEL, BOOL))objc_msgSend)(nsView, sel_registerName("setWantsLayer:"), YES);
VkResult result;
@@ -14695,7 +15836,7 @@ VkResult RGFW_window_createSurface_Vulkan(RGFW_window* win, VkInstance instance,
#ifdef RGFW_WEBGPU
WGPUSurface RGFW_window_createSurface_WebGPU(RGFW_window* window, WGPUInstance instance) {
WGPUSurfaceDescriptor surfaceDesc = {0};
- id* nsView = (id*)window->src.view;
+ id nsView = (id)window->src.view;
if (!nsView) {
RGFW_debugCallback(RGFW_typeError, RGFW_errMetal, "NSView is NULL for macOS window");
return NULL;
@@ -14708,8 +15849,8 @@ WGPUSurface RGFW_window_createSurface_WebGPU(RGFW_window* window, WGPUInstance i
if (metalLayer == NULL) {
return NULL;
}
- ((void (*)(id, SEL, id))objc_msgSend)((id)nsView, sel_registerName("setLayer:"), metalLayer);
- layer = metalLayer;
+ ((void (*)(id, SEL, id))objc_msgSend)((id)nsView, sel_registerName("setLayer:"), (id)metalLayer);
+ layer = (id)metalLayer;
WGPUSurfaceSourceMetalLayer fromMetal = {0};
fromMetal.chain.sType = WGPUSType_SurfaceSourceMetalLayer;
@@ -14764,7 +15905,7 @@ EM_BOOL Emscripten_on_fullscreenchange(int eventType, const EmscriptenFullscreen
_RGFW->root->w = originalW;
_RGFW->root->h = originalH;
} else {
- #if __EMSCRIPTEN_major__ >= 1 && __EMSCRIPTEN_minor__ >= 29 && __EMSCRIPTEN_tiny__ >= 0
+ #if __EMSCRIPTEN_MAJOR__ >= 1 && __EMSCRIPTEN_MINOR__ >= 29 && __EMSCRIPTEN_TINY__ >= 0
EmscriptenFullscreenStrategy FSStrat = {0};
FSStrat.scaleMode = EMSCRIPTEN_FULLSCREEN_SCALE_STRETCH;
FSStrat.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_HIDEF;
@@ -14796,7 +15937,7 @@ EM_BOOL Emscripten_on_focusout(int eventType, const EmscriptenFocusEvent* E, voi
EM_BOOL Emscripten_on_mousemove(int eventType, const EmscriptenMouseEvent* E, void* userData) {
RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
- RGFW_mousePosCallback(_RGFW->root, E->targetX, E->targetY);
+ RGFW_mouseMotionCallback(_RGFW->root, E->targetX, E->targetY);
RGFW_rawMotionCallback(_RGFW->root, E->movementX, E->movementY);
return EM_TRUE;
}
@@ -14838,7 +15979,7 @@ EM_BOOL Emscripten_on_touchstart(int eventType, const EmscriptenTouchEvent* E, v
size_t i;
for (i = 0; i < (size_t)E->numTouches; i++) {
- RGFW_mousePosCallback(_RGFW->root, E->touches[i].targetX, E->touches[i].targetY);
+ RGFW_mouseMotionCallback(_RGFW->root, E->touches[i].targetX, E->touches[i].targetY);
RGFW_rawMotionCallback(_RGFW->root, 0, 0);
RGFW_mouseButtonCallback(_RGFW->root, RGFW_mouseLeft, 1);
}
@@ -14849,11 +15990,11 @@ EM_BOOL Emscripten_on_touchstart(int eventType, const EmscriptenTouchEvent* E, v
EM_BOOL Emscripten_on_touchmove(int eventType, const EmscriptenTouchEvent* E, void* userData) {
RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
- if (!(_RGFW->root->internal.enabledEvents & RGFW_mousePosChangedFlag)) return EM_TRUE;
+ if (!(_RGFW->root->internal.enabledEvents & RGFW_mouseMotionFlag)) return EM_TRUE;
size_t i;
for (i = 0; i < (size_t)E->numTouches; i++) {
- RGFW_mousePosCallback(_RGFW->root, E->touches[i].targetX, E->touches[i].targetY);
+ RGFW_mouseMotionCallback(_RGFW->root, E->touches[i].targetX, E->touches[i].targetY);
RGFW_rawMotionCallback(_RGFW->root, 0, 0);
}
return EM_TRUE;
@@ -14866,7 +16007,7 @@ EM_BOOL Emscripten_on_touchend(int eventType, const EmscriptenTouchEvent* E, voi
size_t i;
for (i = 0; i < (size_t)E->numTouches; i++) {
- RGFW_mousePosCallback(_RGFW->root, E->touches[i].targetX, E->touches[i].targetY);
+ RGFW_mouseMotionCallback(_RGFW->root, E->touches[i].targetX, E->touches[i].targetY);
RGFW_rawMotionCallback(_RGFW->root, 0, 0);
RGFW_mouseButtonCallback(_RGFW->root, RGFW_mouseLeft, 0);
}
@@ -14899,6 +16040,8 @@ void EMSCRIPTEN_KEEPALIVE Emscripten_onDrop(char* file, size_t size) {
RGFW_dataDropCallback(_RGFW->root, file, size, RGFW_dataFile);
}
+void EMSCRIPTEN_KEEPALIVE RGFW_webFree(void* ptr) { free(ptr); }
+
void RGFW_stopCheckEvents(void) {
_RGFW->stopCheckEvents_bool = RGFW_TRUE;
}
@@ -15052,7 +16195,8 @@ void RGFW_initKeycodesPlatform(void) {
_RGFW->keycodes[DOM_VK_F24] = RGFW_keyF24;
}
-i32 RGFW_initPlatform(void) {
+i32 RGFW_initPlatform(const char* className, RGFW_initFlags flags) {
+ RGFW_UNUSED(className); RGFW_UNUSED(flags);
RGFW_monitorNode* node = NULL;
RGFW_monitor monitor;
@@ -15119,7 +16263,7 @@ RGFW_window* RGFW_createWindowPlatform(const char* name, RGFW_windowFlags flags,
}
Module._RGFW_handleKeyEvent(code, codepoint, 1);
- _free(code);
+ Module._RGFW_webFree(code);
},
true);
window.addEventListener("keyup",
@@ -15127,7 +16271,7 @@ RGFW_window* RGFW_createWindowPlatform(const char* name, RGFW_windowFlags flags,
var code = stringToNewUTF8(event.code);
Module._RGFW_handleKeyMods(event.getModifierState("CapsLock"), event.getModifierState("NumLock"), event.getModifierState("Control"), event.getModifierState("Alt"), event.getModifierState("Shift"), event.getModifierState("Meta"), event.getModifierState("ScrollLock"));
Module._RGFW_handleKeyEvent(code, 0, 0);
- _free(code);
+ Module._RGFW_webFree(code);
},
true);
});
@@ -15186,11 +16330,16 @@ RGFW_bool RGFW_window_fetchSize(RGFW_window* win, i32* w, i32* h) {
}
void RGFW_pollEvents(void) {
+ static int using_asyncify = -1;
+ if (using_asyncify == -1) using_asyncify = EM_ASM_INT({ return (typeof Asyncify !== 'undefined') || ('Asyncify' in Module); });
+
RGFW_resetPrevState();
- emscripten_sleep(0);
+ if (using_asyncify) {
+ emscripten_sleep(0);
+ }
}
-void RGFW_window_resize(RGFW_window* win, i32 w, i32 h) {
+void RGFW_window_resizePlatform(RGFW_window* win, i32 w, i32 h) {
RGFW_UNUSED(win);
emscripten_set_canvas_element_size("#canvas", w, h);
}
@@ -15271,27 +16420,32 @@ void RGFW_window_setMousePassthrough(RGFW_window* win, RGFW_bool passthrough) {
}, passthrough);
}
-void RGFW_writeClipboard(const char* text, u32 textLen) {
- RGFW_UNUSED(textLen);
- EM_ASM({ navigator.clipboard.writeText(UTF8ToString($0)); }, text);
+RGFW_bool RGFW_writeClipboard(const RGFW_dataTransfer* data) {
+ RGFW_ASSERT(data != NULL);
+ EM_ASM({ navigator.clipboard.writeText(UTF8ToString($0)); }, data->data);
+ return RGFW_TRUE;
}
-RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity) {
- RGFW_UNUSED(str); RGFW_UNUSED(strCapacity);
+RGFW_bool RGFW_readClipboardPtr(RGFW_dataTransferType requestedType, u8* buffer, size_t capacity, RGFW_dataTransfer* data) {
+ RGFW_ASSERT(data != NULL);
+ RGFW_UNUSED(buffer); RGFW_UNUSED(capacity);
+
+ if (requestedType != RGFW_dataText) return RGFW_FALSE;
+
/*
placeholder code for later
I'm not sure if this is possible do the the async stuff
*/
- return 0;
+ return RGFW_FALSE;
}
#ifdef RGFW_OPENGL
-RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx, RGFW_glHints* hints) {
- win->src.ctx.native = ctx;
- win->src.gfxType = RGFW_gfxNativeOpenGL;
+RGFW_bool RGFW_loadGL(void) { return RGFW_TRUE; }
+RGFW_bool RGFW_createContextPtr_OpenGL(RGFW_glContext* ctx, RGFW_glHints* hints) {
EmscriptenWebGLContextAttributes attrs;
+ emscripten_webgl_init_context_attributes(&attrs);
attrs.alpha = hints->alpha;
attrs.depth = hints->depth;
attrs.stencil = hints->stencil;
@@ -15305,29 +16459,65 @@ RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext*
attrs.renderViaOffscreenBackBuffer = hints->auxBuffers;
attrs.failIfMajorPerformanceCaveat = EM_FALSE;
- attrs.majorVersion = (hints->major == 0) ? 1 : hints->major;
- attrs.minorVersion = hints->minor;
attrs.enableExtensionsByDefault = EM_TRUE;
+
+ if (hints->profile == RGFW_glWeb) {
+ attrs.majorVersion = (hints->major == 0) ? 1 : hints->major;
+ attrs.minorVersion = hints->minor;
+ } else {
+ attrs.majorVersion = (hints->major == 0) ? 1 : ( (hints->major > 1) ? hints->major - 1 : hints->major );
+ attrs.minorVersion = hints->minor;
+ }
+
attrs.explicitSwapControl = EM_TRUE;
+ ctx->ctx = emscripten_webgl_create_context("#canvas", &attrs);
- emscripten_webgl_init_context_attributes(&attrs);
- win->src.ctx.native->ctx = emscripten_webgl_create_context("#canvas", &attrs);
- emscripten_webgl_make_context_current(win->src.ctx.native->ctx);
+ if (ctx->ctx == 0) {
+ RGFW_debugCallback(RGFW_typeError, RGFW_warningOpenGL, "WebGL: Failed to create an OpenGL Context with explicit swap control.");
+ attrs.explicitSwapControl = EM_FALSE;
+ ctx->ctx = emscripten_webgl_create_context("#canvas", &attrs);
+ }
+
+ if (ctx->ctx == 0) {
+ RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to create an OpenGL Context with the requested attributes, falling back to defaults.");
+ ctx->ctx = emscripten_webgl_create_context("#canvas", &attrs);
+ }
+
+ if (ctx->ctx == 0) {
+ RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to create an OpenGL Context.");
+ return RGFW_FALSE;
+ }
+
+ emscripten_webgl_make_context_current(ctx->ctx);
#ifdef LEGACY_GL_EMULATION
EM_ASM("Module.useWebGL = true; GLImmediate.init();");
RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context initalized.");
#endif
- RGFW_window_swapInterval_OpenGL(win, 0);
+ return RGFW_TRUE;
+}
+RGFW_bool RGFW_window_setContext_OpenGL(RGFW_window* win, RGFW_glContext* ctx) {
+ RGFW_ASSERT(win);
+ if (ctx == NULL && win->src.ctx.native != NULL) {
+ win->src.ctx.native = NULL;
+
+ RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL surface freed.");
+ return RGFW_TRUE;
+ }
+
+ win->src.ctx.native = ctx;
+ win->src.gfxType = RGFW_gfxNativeOpenGL;
+
+ RGFW_window_swapInterval_OpenGL(win, 0);
+ RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL surface initalized.");
return RGFW_TRUE;
}
-void RGFW_window_deleteContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx) {
+void RGFW_deleteContextPtr_OpenGL(RGFW_glContext* ctx) {
emscripten_webgl_destroy_context(ctx->ctx);
- win->src.ctx.native->ctx = 0;
RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context freed.");
}
@@ -15344,6 +16534,7 @@ void RGFW_window_swapBuffers_OpenGL(RGFW_window* win) {
emscripten_webgl_commit_frame();
}
void* RGFW_getCurrentContext_OpenGL(void) { return (void*)emscripten_webgl_get_current_context(); }
+void* RGFW_getCurrentSurface_OpenGL(void) { return (void*)emscripten_webgl_get_current_context(); }
RGFW_bool RGFW_extensionSupportedPlatform_OpenGL(const char* extension, size_t len) {
return EM_ASM_INT({
@@ -15394,26 +16585,20 @@ void RGFW_window_setName(RGFW_window* win, const char* name) {
emscripten_set_window_title(name);
}
-void RGFW_window_maximize(RGFW_window* win) {
- RGFW_ASSERT(win != NULL);
-
+void RGFW_window_maximizePlatform(RGFW_window* win) {
RGFW_monitor* mon = RGFW_window_getMonitor(win);
if (mon != NULL) {
RGFW_window_resize(win, mon->mode.w, mon->mode.h);
}
RGFW_window_move(win, 0, 0);
- RGFW_window_fetchSize(win, NULL, NULL);
}
-void RGFW_window_setFullscreen(RGFW_window* win, RGFW_bool fullscreen) {
- RGFW_ASSERT(win != NULL);
+void RGFW_window_setFullscreenPlatform(RGFW_window* win, RGFW_bool fullscreen) {
if (fullscreen) {
- win->internal.flags |= RGFW_windowFullscreen;
EM_ASM( Module.requestFullscreen(false, true); );
return;
}
- win->internal.flags &= ~(u32)RGFW_windowFullscreen;
EM_ASM( Module.exitFullscreen(false, true); );
}
@@ -15462,6 +16647,7 @@ RGFW_key RGFW_WASMPhysicalToRGFW(u32 hash) {
case 0x2C595B54U /* KeyT */: return RGFW_keyT; /* 0x0014 */
case 0x2C595B59U /* KeyY */: return RGFW_keyY; /* 0x0015 */
case 0x2C595B55U /* KeyU */: return RGFW_keyU; /* 0x0016 */
+ case 0x2C595B49U /* KeyI */: return RGFW_keyI; /* 0x0017 */
case 0x2C595B4FU /* KeyO */: return RGFW_keyO; /* 0x0018 */
case 0x2C595B50U /* KeyP */: return RGFW_keyP; /* 0x0019 */
case 0x45D8158CU /* BracketLeft */: return RGFW_keyCloseBracket; /* 0x001A */
@@ -15507,7 +16693,7 @@ RGFW_key RGFW_WASMPhysicalToRGFW(u32 hash) {
case 0x7174B780U /* F8 */: return RGFW_keyF8; /* 0x0042 */
case 0x7174B781U /* F9 */: return RGFW_keyF9; /* 0x0043 */
case 0x7B8E57B0U /* F10 */: return RGFW_keyF10; /* 0x0044 */
- case 0xC925FCDFU /* Numpad7 */: return RGFW_keyPadMultiply; /* 0x0047 */
+ case 0xC925FCDFU /* Numpad7 */: return RGFW_key7; /* 0x0047 */
case 0xC925FCD0U /* Numpad8 */: return RGFW_keyPad8; /* 0x0048 */
case 0xC925FCD1U /* Numpad9 */: return RGFW_keyPad9; /* 0x0049 */
case 0x5EA3E8A4U /* NumpadSubtract */: return RGFW_keyMinus; /* 0x004A */
@@ -15521,17 +16707,17 @@ RGFW_key RGFW_WASMPhysicalToRGFW(u32 hash) {
case 0x95852DACU /* NumpadDecimal */: return RGFW_keyPeriod; /* 0x0053 */
case 0x7B8E57B1U /* F11 */: return RGFW_keyF11; /* 0x0057 */
case 0x7B8E57B2U /* F12 */: return RGFW_keyF12; /* 0x0058 */
- case 0x7B8E57B3U /* F13 */: return DOM_PK_F13; /* 0x0064 */
- case 0x7B8E57B4U /* F14 */: return DOM_PK_F14; /* 0x0065 */
- case 0x7B8E57B5U /* F15 */: return DOM_PK_F15; /* 0x0066 */
- case 0x7B8E57B6U /* F16 */: return DOM_PK_F16; /* 0x0067 */
- case 0x7B8E57B7U /* F17 */: return DOM_PK_F17; /* 0x0068 */
- case 0x7B8E57B8U /* F18 */: return DOM_PK_F18; /* 0x0069 */
- case 0x7B8E57B9U /* F19 */: return DOM_PK_F19; /* 0x006A */
- case 0x7B8E57A8U /* F20 */: return DOM_PK_F20; /* 0x006B */
- case 0x7B8E57A9U /* F21 */: return DOM_PK_F21; /* 0x006C */
- case 0x7B8E57AAU /* F22 */: return DOM_PK_F22; /* 0x006D */
- case 0x7B8E57ABU /* F23 */: return DOM_PK_F23; /* 0x006E */
+ case 0x7B8E57B3U /* F13 */: return RGFW_keyF13; /* 0x0064 */
+ case 0x7B8E57B4U /* F14 */: return RGFW_keyF14; /* 0x0065 */
+ case 0x7B8E57B5U /* F15 */: return RGFW_keyF15; /* 0x0066 */
+ case 0x7B8E57B6U /* F16 */: return RGFW_keyF16; /* 0x0067 */
+ case 0x7B8E57B7U /* F17 */: return RGFW_keyF17; /* 0x0068 */
+ case 0x7B8E57B8U /* F18 */: return RGFW_keyF18; /* 0x0069 */
+ case 0x7B8E57B9U /* F19 */: return RGFW_keyF19; /* 0x006A */
+ case 0x7B8E57A8U /* F20 */: return RGFW_keyF20; /* 0x006B */
+ case 0x7B8E57A9U /* F21 */: return RGFW_keyF21; /* 0x006C */
+ case 0x7B8E57AAU /* F22 */: return RGFW_keyF22; /* 0x006D */
+ case 0x7B8E57ABU /* F23 */: return RGFW_keyF23; /* 0x006E */
case 0x7393FBACU /* NumpadEqual */: return RGFW_keyPadReturn;
case 0xB88EBF7CU /* AltRight */: return RGFW_keyAltR; /* 0xE038 */
case 0xC925873BU /* NumLock */: return RGFW_keyNumLock; /* 0xE045 */
@@ -15547,7 +16733,13 @@ RGFW_key RGFW_WASMPhysicalToRGFW(u32 hash) {
case 0x6725C50DU /* Delete */: return RGFW_keyDelete; /* 0xE053 */
case 0x6723658CU /* OSLeft */: return RGFW_keySuperL; /* 0xE05B */
case 0x39643F7CU /* MetaRight */: return RGFW_keySuperR; /* 0xE05C */
- case 0x380B9C8CU /* NumpadAdd */: return DOM_PK_NUMPAD_ADD; /* 0x004E */
+ case 0x380B9C8CU /* NumpadAdd */: return RGFW_keyPadPlus; /* 0x004E */
+ case 0x92E08B35U /* Pause */: return RGFW_keyPause; /* 0x0045 */
+ case 0xCC1E198EU /* PrintScreen */: return RGFW_keyPrintScreen; /* 0x0054 */
+ case 0xCDED173BU /* ScrollLock */: return RGFW_keyScrollLock; /* 0x0046 */
+ case 0x7393C5D2U /* NumpadEnter */: return RGFW_keyPadReturn; /* 0xE01C */
+ case 0xE00E97CDU /* ContextMenu */: return RGFW_keyMenu; /* 0xE05D */
+ case 0x6CB5328DU /* NumpadDivide */: return RGFW_keyPadSlash; /* 0xE035 */
default: return DOM_PK_UNKNOWN;
}
@@ -15561,6 +16753,7 @@ RGFW_monitor* RGFW_window_getMonitor(RGFW_window* win) {
/* unsupported functions */
void RGFW_pollMonitors(void) { }
+void RGFW_monitorNode_free(RGFW_monitorNode* node) { RGFW_UNUSED(node); }
void RGFW_window_focus(RGFW_window* win) { RGFW_UNUSED(win); }
void RGFW_window_raise(RGFW_window* win) { RGFW_UNUSED(win); }
RGFW_bool RGFW_monitor_requestMode(RGFW_monitor* mon, RGFW_monitorMode* mode, RGFW_modeRequest request) { RGFW_UNUSED(mon); RGFW_UNUSED(mode); RGFW_UNUSED(request); return RGFW_FALSE; }
@@ -15569,17 +16762,17 @@ size_t RGFW_monitor_getGammaRampPtr(RGFW_monitor* monitor, RGFW_gammaRamp* ramp)
RGFW_bool RGFW_monitor_setGammaRamp(RGFW_monitor* monitor, RGFW_gammaRamp* ramp) { RGFW_UNUSED(monitor); RGFW_UNUSED(ramp); return RGFW_FALSE; }
size_t RGFW_monitor_getModesPtr(RGFW_monitor* mon, RGFW_monitorMode** modes) { RGFW_UNUSED(mon); RGFW_UNUSED(modes); return 0; }
RGFW_bool RGFW_monitor_setMode(RGFW_monitor* mon, RGFW_monitorMode* mode) { RGFW_UNUSED(mon); RGFW_UNUSED(mode); return RGFW_FALSE; }
-void RGFW_window_move(RGFW_window* win, i32 x, i32 y) { RGFW_UNUSED(win); RGFW_UNUSED(x); RGFW_UNUSED(y); }
+void RGFW_window_movePlatform(RGFW_window* win, i32 x, i32 y) { RGFW_UNUSED(win); RGFW_UNUSED(x); RGFW_UNUSED(y); }
void RGFW_window_setAspectRatio(RGFW_window* win, i32 w, i32 h) { RGFW_UNUSED(win); RGFW_UNUSED(w); RGFW_UNUSED(h); }
void RGFW_window_setMinSize(RGFW_window* win, i32 w, i32 h) { RGFW_UNUSED(win); RGFW_UNUSED(w); RGFW_UNUSED(h); }
void RGFW_window_setMaxSize(RGFW_window* win, i32 w, i32 h) { RGFW_UNUSED(win); RGFW_UNUSED(w); RGFW_UNUSED(h); }
-void RGFW_window_minimize(RGFW_window* win) { RGFW_UNUSED(win); }
-void RGFW_window_restore(RGFW_window* win) { RGFW_UNUSED(win); }
+void RGFW_window_minimizePlatform(RGFW_window* win) { RGFW_UNUSED(win); }
+void RGFW_window_restorePlatform(RGFW_window* win) { RGFW_UNUSED(win); }
void RGFW_window_setFloating(RGFW_window* win, RGFW_bool floating) { RGFW_UNUSED(win); RGFW_UNUSED(floating); }
void RGFW_window_setBorder(RGFW_window* win, RGFW_bool border) { RGFW_UNUSED(win); RGFW_UNUSED(border); }
RGFW_bool RGFW_window_setIconEx(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, RGFW_icon type) { RGFW_UNUSED(win); RGFW_UNUSED(data); RGFW_UNUSED(w); RGFW_UNUSED(h); RGFW_UNUSED(format); RGFW_UNUSED(type); return RGFW_FALSE; }
void RGFW_window_hide(RGFW_window* win) { RGFW_UNUSED(win); }
-void RGFW_window_show(RGFW_window* win) {RGFW_UNUSED(win); }
+void RGFW_window_showPlatform(RGFW_window* win) {RGFW_UNUSED(win); }
void RGFW_window_flash(RGFW_window* win, RGFW_flashRequest request) { RGFW_UNUSED(win); RGFW_UNUSED(request); }
RGFW_bool RGFW_window_isHidden(RGFW_window* win) { RGFW_UNUSED(win); return RGFW_FALSE; }
RGFW_bool RGFW_window_isMinimized(RGFW_window* win) { RGFW_UNUSED(win); return RGFW_FALSE; }
@@ -15600,6 +16793,7 @@ typedef RGFW_key (*RGFW_physicalToMappedKey_ptr)(RGFW_key key);
typedef void (*RGFW_pollEvents_ptr)(void);
typedef RGFW_bool (*RGFW_window_fetchSize_ptr)(RGFW_window* win, i32* w, i32* h);
typedef void (*RGFW_pollMonitors_ptr)(void);
+typedef void (*RGFW_monitorNode_free_ptr)(RGFW_monitorNode* node);
typedef void (*RGFW_window_move_ptr)(RGFW_window* win, i32 x, i32 y);
typedef void (*RGFW_window_resize_ptr)(RGFW_window* win, i32 w, i32 h);
typedef void (*RGFW_window_setAspectRatio_ptr)(RGFW_window* win, i32 w, i32 h);
@@ -15608,7 +16802,7 @@ typedef void (*RGFW_window_setMaxSize_ptr)(RGFW_window* win, i32 w, i32 h);
typedef void (*RGFW_window_maximize_ptr)(RGFW_window* win);
typedef void (*RGFW_window_focus_ptr)(RGFW_window* win);
typedef void (*RGFW_window_raise_ptr)(RGFW_window* win);
-typedef void (*RGFW_window_setFullscreen_ptr)(RGFW_window* win, RGFW_bool fullscreen);
+typedef void (*RGFW_window_setFullscreenPlatform_ptr)(RGFW_window* win, RGFW_bool fullscreen);
typedef void (*RGFW_window_setFloating_ptr)(RGFW_window* win, RGFW_bool floating);
typedef void (*RGFW_window_setOpacity_ptr)(RGFW_window* win, u8 opacity);
typedef void (*RGFW_window_minimize_ptr)(RGFW_window* win);
@@ -15624,8 +16818,8 @@ typedef void (*RGFW_window_moveMouse_ptr)(RGFW_window* win, i32 x, i32 y);
typedef void (*RGFW_window_hide_ptr)(RGFW_window* win);
typedef void (*RGFW_window_show_ptr)(RGFW_window* win);
typedef void (*RGFW_window_flash_ptr)(RGFW_window* win, RGFW_flashRequest request);
-typedef RGFW_ssize_t (*RGFW_readClipboardPtr_ptr)(char* str, size_t strCapacity);
-typedef void (*RGFW_writeClipboard_ptr)(const char* text, u32 textLen);
+typedef RGFW_bool (*RGFW_readClipboardPtr_ptr)(RGFW_dataTransferType requestedType, u8* buffer, size_t capacity, RGFW_dataTransfer* data);
+typedef RGFW_bool (*RGFW_writeClipboard_ptr)(const RGFW_dataTransfer* data);
typedef RGFW_bool (*RGFW_window_isHidden_ptr)(RGFW_window* win);
typedef RGFW_bool (*RGFW_window_isMinimized_ptr)(RGFW_window* win);
typedef RGFW_bool (*RGFW_window_isMaximized_ptr)(RGFW_window* win);
@@ -15648,12 +16842,14 @@ typedef void (*RGFW_window_setRawMouseModePlatform_ptr)(RGFW_window* win, RGFW_b
#ifdef RGFW_OPENGL
typedef void (*RGFW_window_makeCurrentContext_OpenGL_ptr)(RGFW_window* win);
typedef void* (*RGFW_getCurrentContext_OpenGL_ptr)(void);
+typedef void* (*RGFW_getCurrentSurface_OpenGL_ptr)(void);
typedef void (*RGFW_window_swapBuffers_OpenGL_ptr)(RGFW_window* win);
typedef void (*RGFW_window_swapInterval_OpenGL_ptr)(RGFW_window* win, i32 swapInterval);
typedef RGFW_bool (*RGFW_extensionSupportedPlatform_OpenGL_ptr)(const char* extension, size_t len);
typedef RGFW_proc (*RGFW_getProcAddress_OpenGL_ptr)(const char* procname);
-typedef RGFW_bool (*RGFW_window_createContextPtr_OpenGL_ptr)(RGFW_window* win, RGFW_glContext* ctx, RGFW_glHints* hints);
-typedef void (*RGFW_window_deleteContextPtr_OpenGL_ptr)(RGFW_window* win, RGFW_glContext* ctx);
+typedef RGFW_bool (*RGFW_createContextPtr_OpenGL_ptr)(RGFW_glContext* ctx, RGFW_glHints* hints);
+typedef RGFW_bool (*RGFW_window_setContext_OpenGL_ptr)(RGFW_window* win, RGFW_glContext* ctx);
+typedef void (*RGFW_deleteContextPtr_OpenGL_ptr)(RGFW_glContext* ctx);
#endif
#ifdef RGFW_WEBGPU
typedef WGPUSurface (*RGFW_window_createSurface_WebGPU_ptr)(RGFW_window* window, WGPUInstance instance);
@@ -15675,25 +16871,26 @@ typedef struct RGFW_FunctionPointers {
RGFW_window_fetchSize_ptr window_fetchSize;
RGFW_pollEvents_ptr pollEvents;
RGFW_pollMonitors_ptr pollMonitors;
- RGFW_window_move_ptr window_move;
- RGFW_window_resize_ptr window_resize;
+ RGFW_monitorNode_free_ptr monitorNode_free;
+ RGFW_window_move_ptr window_movePlatform;
+ RGFW_window_resize_ptr window_resizePlatform;
RGFW_window_setAspectRatio_ptr window_setAspectRatio;
RGFW_window_setMinSize_ptr window_setMinSize;
RGFW_window_setMaxSize_ptr window_setMaxSize;
- RGFW_window_maximize_ptr window_maximize;
+ RGFW_window_maximize_ptr window_maximizePlatform;
RGFW_window_focus_ptr window_focus;
RGFW_window_raise_ptr window_raise;
- RGFW_window_setFullscreen_ptr window_setFullscreen;
+ RGFW_window_setFullscreenPlatform_ptr window_setFullscreenPlatform;
RGFW_window_setFloating_ptr window_setFloating;
RGFW_window_setOpacity_ptr window_setOpacity;
- RGFW_window_minimize_ptr window_minimize;
- RGFW_window_restore_ptr window_restore;
+ RGFW_window_minimize_ptr window_minimizePlatform;
+ RGFW_window_restore_ptr window_restorePlatform;
RGFW_window_isFloating_ptr window_isFloating;
RGFW_window_setName_ptr window_setName;
RGFW_window_setMousePassthrough_ptr window_setMousePassthrough;
RGFW_window_setIconEx_ptr window_setIconEx;
- RGFW_createMouse_ptr loadMouse;
- RGFW_createMouseStandard_ptr loadMouseStandard;
+ RGFW_createMouse_ptr createMouse;
+ RGFW_createMouseStandard_ptr createMouseStandard;
RGFW_window_setMousePlatform_ptr window_setMousePlatform;
RGFW_window_moveMouse_ptr window_moveMouse;
RGFW_window_hide_ptr window_hide;
@@ -15715,10 +16912,12 @@ typedef struct RGFW_FunctionPointers {
#ifdef RGFW_OPENGL
RGFW_extensionSupportedPlatform_OpenGL_ptr extensionSupportedPlatform_OpenGL;
RGFW_getProcAddress_OpenGL_ptr getProcAddress_OpenGL;
- RGFW_window_createContextPtr_OpenGL_ptr window_createContextPtr_OpenGL;
- RGFW_window_deleteContextPtr_OpenGL_ptr window_deleteContextPtr_OpenGL;
+ RGFW_createContextPtr_OpenGL_ptr createContextPtr_OpenGL;
+ RGFW_window_setContext_OpenGL_ptr window_setContext_OpenGL;
+ RGFW_deleteContextPtr_OpenGL_ptr deleteContextPtr_OpenGL;
RGFW_window_makeCurrentContext_OpenGL_ptr window_makeCurrentContext_OpenGL;
RGFW_getCurrentContext_OpenGL_ptr getCurrentContext_OpenGL;
+ RGFW_getCurrentSurface_OpenGL_ptr getCurrentSurface_OpenGL;
RGFW_window_swapBuffers_OpenGL_ptr window_swapBuffers_OpenGL;
RGFW_window_swapInterval_OpenGL_ptr window_swapInterval_OpenGL;
#endif
@@ -15737,25 +16936,26 @@ void RGFW_window_blitSurface(RGFW_window* win, RGFW_surface* surface) { RGFW_api
void RGFW_window_setBorder(RGFW_window* win, RGFW_bool border) { RGFW_api.window_setBorder(win, border); }
void RGFW_window_captureMousePlatform(RGFW_window* win, RGFW_bool state) { RGFW_api.window_captureMousePlatform(win, state); }
void RGFW_window_setRawMouseModePlatform(RGFW_window* win, RGFW_bool state) { RGFW_api.window_setRawMouseModePlatform(win, state); }
-RGFW_window* RGFW_createWindowPlatform(const char* name, RGFW_windowFlags flags, RGFW_window* win) { RGFW_init(); return RGFW_api.createWindowPlatform(name, flags, win); }
+RGFW_window* RGFW_createWindowPlatform(const char* name, RGFW_windowFlags flags, RGFW_window* win) { return RGFW_api.createWindowPlatform(name, flags, win); }
RGFW_bool RGFW_getGlobalMouse(i32* x, i32* y) { return RGFW_api.getGlobalMouse(x, y); }
RGFW_key RGFW_physicalToMappedKey(RGFW_key key) { return RGFW_api.physicalToMappedKey(key); }
void RGFW_pollEvents(void) { RGFW_api.pollEvents(); }
RGFW_bool RGFW_window_fetchSize(RGFW_window* win, i32* w, i32* h) { return RGFW_api.window_fetchSize(win, w, h); }
void RGFW_pollMonitors(void) { RGFW_api.pollMonitors(); }
-void RGFW_window_move(RGFW_window* win, i32 x, i32 y) { RGFW_api.window_move(win, x, y); }
-void RGFW_window_resize(RGFW_window* win, i32 w, i32 h) { RGFW_api.window_resize(win, w, h); }
+void RGFW_monitorNode_free(RGFW_monitorNode* node) { RGFW_api.monitorNode_free(node); }
+void RGFW_window_movePlatform(RGFW_window* win, i32 x, i32 y) { RGFW_api.window_movePlatform(win, x, y); }
+void RGFW_window_resizePlatform(RGFW_window* win, i32 w, i32 h) { RGFW_api.window_resizePlatform(win, w, h); }
void RGFW_window_setAspectRatio(RGFW_window* win, i32 w, i32 h) { RGFW_api.window_setAspectRatio(win, w, h); }
void RGFW_window_setMinSize(RGFW_window* win, i32 w, i32 h) { RGFW_api.window_setMinSize(win, w, h); }
void RGFW_window_setMaxSize(RGFW_window* win, i32 w, i32 h) { RGFW_api.window_setMaxSize(win, w, h); }
-void RGFW_window_maximize(RGFW_window* win) { RGFW_api.window_maximize(win); }
+void RGFW_window_maximizePlatform(RGFW_window* win) { RGFW_api.window_maximizePlatform(win); }
void RGFW_window_focus(RGFW_window* win) { RGFW_api.window_focus(win); }
void RGFW_window_raise(RGFW_window* win) { RGFW_api.window_raise(win); }
-void RGFW_window_setFullscreen(RGFW_window* win, RGFW_bool fullscreen) { RGFW_api.window_setFullscreen(win, fullscreen); }
+void RGFW_window_setFullscreenPlatform(RGFW_window* win, RGFW_bool fullscreen) { RGFW_api.window_setFullscreenPlatform(win, fullscreen); }
void RGFW_window_setFloating(RGFW_window* win, RGFW_bool floating) { RGFW_api.window_setFloating(win, floating); }
void RGFW_window_setOpacity(RGFW_window* win, u8 opacity) { RGFW_api.window_setOpacity(win, opacity); }
-void RGFW_window_minimize(RGFW_window* win) { RGFW_api.window_minimize(win); }
-void RGFW_window_restore(RGFW_window* win) { RGFW_api.window_restore(win); }
+void RGFW_window_minimizePlatform(RGFW_window* win) { RGFW_api.window_minimizePlatform(win); }
+void RGFW_window_restorePlatform(RGFW_window* win) { RGFW_api.window_restorePlatform(win); }
RGFW_bool RGFW_window_isFloating(RGFW_window* win) { return RGFW_api.window_isFloating(win); }
void RGFW_window_setName(RGFW_window* win, const char* name) { RGFW_api.window_setName(win, name); }
@@ -15764,15 +16964,15 @@ void RGFW_window_setMousePassthrough(RGFW_window* win, RGFW_bool passthrough) {
#endif
RGFW_bool RGFW_window_setIconEx(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, u8 type) { return RGFW_api.window_setIconEx(win, data, w, h, format, type); }
-RGFW_mouse* RGFW_createMouse(u8* data, i32 w, i32 h, RGFW_format format) { return RGFW_api.loadMouse(data, w, h, format); }
-RGFW_mouse* RGFW_createMouseStandard(RGFW_mouseIcon icon) { return RGFW_api.loadMouseStandard(icon); }
+RGFW_mouse* RGFW_createMouse(u8* data, i32 w, i32 h, RGFW_format format) { return RGFW_api.createMouse(data, w, h, format); }
+RGFW_mouse* RGFW_createMouseStandard(RGFW_mouseIcon icon) { return RGFW_api.createMouseStandard(icon); }
RGFW_bool RGFW_window_setMousePlatform(RGFW_window* win, RGFW_mouse* mouse) { return RGFW_api.window_setMousePlatform(win, mouse); }
void RGFW_window_moveMouse(RGFW_window* win, i32 x, i32 y) { RGFW_api.window_moveMouse(win, x, y); }
void RGFW_window_hide(RGFW_window* win) { RGFW_api.window_hide(win); }
-void RGFW_window_show(RGFW_window* win) { RGFW_api.window_show(win); }
+void RGFW_window_showPlatform(RGFW_window* win) { RGFW_api.window_show(win); }
void RGFW_window_flash(RGFW_window* win, RGFW_flashRequest request) { RGFW_api.window_flash(win, request); }
-RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity) { return RGFW_api.readClipboardPtr(str, strCapacity); }
-void RGFW_writeClipboard(const char* text, u32 textLen) { RGFW_api.writeClipboard(text, textLen); }
+RGFW_bool RGFW_readClipboardPtr(RGFW_dataTransferType requestedType, u8* buffer, size_t capacity, RGFW_dataTransfer* data) { return RGFW_api.readClipboardPtr(requestedType, buffer, capacity, data); }
+RGFW_bool RGFW_writeClipboard(const RGFW_dataTransfer* data) { return RGFW_api.writeClipboard(data); }
RGFW_bool RGFW_window_isHidden(RGFW_window* win) { return RGFW_api.window_isHidden(win); }
RGFW_bool RGFW_window_isMinimized(RGFW_window* win) { return RGFW_api.window_isMinimized(win); }
RGFW_bool RGFW_window_isMaximized(RGFW_window* win) { return RGFW_api.window_isMaximized(win); }
@@ -15788,10 +16988,12 @@ void RGFW_window_closePlatform(RGFW_window* win) { RGFW_api.window_closePlatform
#ifdef RGFW_OPENGL
RGFW_bool RGFW_extensionSupportedPlatform_OpenGL(const char* extension, size_t len) { return RGFW_api.extensionSupportedPlatform_OpenGL(extension, len); }
RGFW_proc RGFW_getProcAddress_OpenGL(const char* procname) { return RGFW_api.getProcAddress_OpenGL(procname); }
-RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx, RGFW_glHints* hints) { return RGFW_api.window_createContextPtr_OpenGL(win, ctx, hints); }
-void RGFW_window_deleteContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx) { RGFW_api.window_deleteContextPtr_OpenGL(win, ctx); }
+RGFW_bool RGFW_createContextPtr_OpenGL(RGFW_glContext* ctx, RGFW_glHints* hints) { return RGFW_api.createContextPtr_OpenGL(ctx, hints); }
+RGFW_bool RGFW_window_setContext_OpenGL(RGFW_window* win, RGFW_glContext* ctx) { return RGFW_api.window_setContext_OpenGL(win, ctx); }
+void RGFW_deleteContextPtr_OpenGL(RGFW_glContext* ctx) { RGFW_api.deleteContextPtr_OpenGL(ctx); }
void RGFW_window_makeCurrentContext_OpenGL(RGFW_window* win) { RGFW_api.window_makeCurrentContext_OpenGL(win); }
void* RGFW_getCurrentContext_OpenGL(void) { return RGFW_api.getCurrentContext_OpenGL(); }
+void* RGFW_getCurrentSurface_OpenGL(void) { return RGFW_api.getCurrentSurface_OpenGL(); }
void RGFW_window_swapBuffers_OpenGL(RGFW_window* win) { RGFW_api.window_swapBuffers_OpenGL(win); }
void RGFW_window_swapInterval_OpenGL(RGFW_window* win, i32 swapInterval) { RGFW_api.window_swapInterval_OpenGL(win, swapInterval); }
#endif
@@ -15807,6 +17009,8 @@ WGPUSurface RGFW_window_createSurface_WebGPU(RGFW_window* window, WGPUInstance i
* falling back to x11 if wayland fails to initalize
*/
#if defined(RGFW_WAYLAND) && defined(RGFW_X11)
+RGFW_bool RGFW_usingWayland(void) { return _RGFW->useWaylandBool; }
+
void RGFW_load_X11(void) {
RGFW_api.nativeFormat = RGFW_nativeFormat_X11;
RGFW_api.createSurfacePtr = RGFW_createSurfacePtr_X11;
@@ -15822,30 +17026,31 @@ void RGFW_load_X11(void) {
RGFW_api.pollEvents = RGFW_pollEvents_X11;
RGFW_api.window_fetchSize = RGFW_window_fetchSize_X11;
RGFW_api.pollMonitors = RGFW_pollMonitors_X11;
- RGFW_api.window_move = RGFW_window_move_X11;
- RGFW_api.window_resize = RGFW_window_resize_X11;
+ RGFW_api.window_movePlatform = RGFW_window_movePlatform_X11;
+ RGFW_api.window_resizePlatform = RGFW_window_resizePlatform_X11;
RGFW_api.window_setAspectRatio = RGFW_window_setAspectRatio_X11;
RGFW_api.window_setMinSize = RGFW_window_setMinSize_X11;
RGFW_api.window_setMaxSize = RGFW_window_setMaxSize_X11;
- RGFW_api.window_maximize = RGFW_window_maximize_X11;
+ RGFW_api.window_maximizePlatform = RGFW_window_maximizePlatform_X11;
RGFW_api.window_focus = RGFW_window_focus_X11;
RGFW_api.window_raise = RGFW_window_raise_X11;
- RGFW_api.window_setFullscreen = RGFW_window_setFullscreen_X11;
+ RGFW_api.window_setFullscreenPlatform = RGFW_window_setFullscreenPlatform_X11;
RGFW_api.window_setFloating = RGFW_window_setFloating_X11;
RGFW_api.window_setOpacity = RGFW_window_setOpacity_X11;
- RGFW_api.window_minimize = RGFW_window_minimize_X11;
- RGFW_api.window_restore = RGFW_window_restore_X11;
+ RGFW_api.window_minimizePlatform = RGFW_window_minimizePlatform_X11;
+ RGFW_api.window_restorePlatform = RGFW_window_restorePlatform_X11;
RGFW_api.window_isFloating = RGFW_window_isFloating_X11;
RGFW_api.window_setName = RGFW_window_setName_X11;
#ifndef RGFW_NO_PASSTHROUGH
RGFW_api.window_setMousePassthrough = RGFW_window_setMousePassthrough_X11;
#endif
RGFW_api.window_setIconEx = RGFW_window_setIconEx_X11;
- RGFW_api.loadMouse = RGFW_createMouse_X11;
+ RGFW_api.createMouse = RGFW_createMouse_X11;
+ RGFW_api.createMouseStandard = RGFW_createMouseStandard_X11;
RGFW_api.window_setMousePlatform = RGFW_window_setMousePlatform_X11;
RGFW_api.window_moveMouse = RGFW_window_moveMouse_X11;
RGFW_api.window_hide = RGFW_window_hide_X11;
- RGFW_api.window_show = RGFW_window_show_X11;
+ RGFW_api.window_show = RGFW_window_showPlatform_X11;
RGFW_api.window_flash = RGFW_window_flash_X11;
RGFW_api.readClipboardPtr = RGFW_readClipboardPtr_X11;
RGFW_api.writeClipboard = RGFW_writeClipboard_X11;
@@ -15856,17 +17061,40 @@ void RGFW_load_X11(void) {
RGFW_api.monitor_getModesPtr = RGFW_monitor_getModesPtr_X11;
RGFW_api.monitor_setGammaRamp = RGFW_monitor_setGammaRamp_X11;
RGFW_api.monitor_getGammaRampPtr = RGFW_monitor_getGammaRampPtr_X11;
- RGFW_api.monitor_setMode = RGFW_monitor_setMode_X11;
+ RGFW_api.window_setRawMouseModePlatform = RGFW_window_setRawMouseModePlatform_Wayland;
+ RGFW_api.createWindowPlatform = RGFW_createWindowPlatform_Wayland;
+ RGFW_api.getGlobalMouse = RGFW_getGlobalMouse_Wayland;
+ RGFW_api.physicalToMappedKey = RGFW_physicalToMappedKey_Wayland;
+ RGFW_api.pollEvents = RGFW_pollEvents_Wayland;
+ RGFW_api.window_fetchSize = RGFW_window_fetchSize_Wayland;
+ RGFW_api.pollMonitors = RGFW_pollMonitors_Wayland;
+ RGFW_api.window_movePlatform = RGFW_window_movePlatform_Wayland;
+ RGFW_api.window_resizePlatform = RGFW_window_resizePlatform_Wayland;
+ RGFW_api.window_setAspectRatio = RGFW_window_setAspectRatio_Wayland;
+ RGFW_api.window_setMinSize = RGFW_window_setMinSize_Wayland;
+ RGFW_api.window_setMaxSize = RGFW_window_setMaxSize_Wayland;
+ RGFW_api.window_maximizePlatform = RGFW_window_maximizePlatform_Wayland;
+ RGFW_api.window_focus = RGFW_window_focus_Wayland;
+ RGFW_api.window_raise = RGFW_window_raise_Wayland;
+ RGFW_api.window_setFullscreenPlatform = RGFW_window_setFullscreenPlatform_Wayland;
+ RGFW_api.window_setFloating = RGFW_window_setFloating_Wayland;
+ RGFW_api.window_setOpacity = RGFW_window_setOpacity_Wayland;
+ RGFW_api.window_minimizePlatform = RGFW_window_minimizePlatform_Wayland;
+ RGFW_api.window_restorePlatform = RGFW_window_restorePlatform_Wayland;
+ RGFW_api.window_isFloating = RGFW_window_isFloating_Wayland;
+ RGFW_api.window_setName = RGFW_window_setName_Wayland;RGFW_api.monitor_setMode = RGFW_monitor_setMode_X11;
RGFW_api.window_getMonitor = RGFW_window_getMonitor_X11;
RGFW_api.window_closePlatform = RGFW_window_closePlatform_X11;
#ifdef RGFW_OPENGL
RGFW_api.extensionSupportedPlatform_OpenGL = RGFW_extensionSupportedPlatform_OpenGL_X11;
RGFW_api.getProcAddress_OpenGL = RGFW_getProcAddress_OpenGL_X11;
- RGFW_api.window_createContextPtr_OpenGL = RGFW_window_createContextPtr_OpenGL_X11;
- RGFW_api.window_deleteContextPtr_OpenGL = RGFW_window_deleteContextPtr_OpenGL_X11;
+ RGFW_api.createContextPtr_OpenGL = RGFW_createContextPtr_OpenGL_X11;
+ RGFW_api.deleteContextPtr_OpenGL = RGFW_deleteContextPtr_OpenGL_X11;
RGFW_api.window_makeCurrentContext_OpenGL = RGFW_window_makeCurrentContext_OpenGL_X11;
RGFW_api.getCurrentContext_OpenGL = RGFW_getCurrentContext_OpenGL_X11;
+ RGFW_api.getCurrentSurface_OpenGL = RGFW_getCurrentSurface_OpenGL_X11;
RGFW_api.window_swapBuffers_OpenGL = RGFW_window_swapBuffers_OpenGL_X11;
+ RGFW_api.window_setContext_OpenGL = RGFW_window_setContext_OpenGL_X11;
RGFW_api.window_swapInterval_OpenGL = RGFW_window_swapInterval_OpenGL_X11;
#endif
#ifdef RGFW_WEBGPU
@@ -15882,37 +17110,16 @@ void RGFW_load_Wayland(void) {
RGFW_api.freeMouse = RGFW_freeMouse_Wayland;
RGFW_api.window_setBorder = RGFW_window_setBorder_Wayland;
RGFW_api.window_captureMousePlatform = RGFW_window_captureMousePlatform_Wayland;
- RGFW_api.window_setRawMouseModePlatform = RGFW_window_setRawMouseModePlatform_Wayland;
- RGFW_api.createWindowPlatform = RGFW_createWindowPlatform_Wayland;
- RGFW_api.getGlobalMouse = RGFW_getGlobalMouse_Wayland;
- RGFW_api.physicalToMappedKey = RGFW_physicalToMappedKey_Wayland;
- RGFW_api.pollEvents = RGFW_pollEvents_Wayland;
- RGFW_api.window_fetchSize = RGFW_window_fetchSize_Wayland;
- RGFW_api.pollMonitors = RGFW_pollMonitors_Wayland;
- RGFW_api.window_move = RGFW_window_move_Wayland;
- RGFW_api.window_resize = RGFW_window_resize_Wayland;
- RGFW_api.window_setAspectRatio = RGFW_window_setAspectRatio_Wayland;
- RGFW_api.window_setMinSize = RGFW_window_setMinSize_Wayland;
- RGFW_api.window_setMaxSize = RGFW_window_setMaxSize_Wayland;
- RGFW_api.window_maximize = RGFW_window_maximize_Wayland;
- RGFW_api.window_focus = RGFW_window_focus_Wayland;
- RGFW_api.window_raise = RGFW_window_raise_Wayland;
- RGFW_api.window_setFullscreen = RGFW_window_setFullscreen_Wayland;
- RGFW_api.window_setFloating = RGFW_window_setFloating_Wayland;
- RGFW_api.window_setOpacity = RGFW_window_setOpacity_Wayland;
- RGFW_api.window_minimize = RGFW_window_minimize_Wayland;
- RGFW_api.window_restore = RGFW_window_restore_Wayland;
- RGFW_api.window_isFloating = RGFW_window_isFloating_Wayland;
- RGFW_api.window_setName = RGFW_window_setName_Wayland;
#ifndef RGFW_NO_PASSTHROUGH
RGFW_api.window_setMousePassthrough = RGFW_window_setMousePassthrough_Wayland;
#endif
RGFW_api.window_setIconEx = RGFW_window_setIconEx_Wayland;
- RGFW_api.loadMouse = RGFW_createMouse_Wayland;
+ RGFW_api.createMouse = RGFW_createMouse_Wayland;
+ RGFW_api.createMouseStandard = RGFW_createMouseStandard_Wayland;
RGFW_api.window_setMousePlatform = RGFW_window_setMousePlatform_Wayland;
RGFW_api.window_moveMouse = RGFW_window_moveMouse_Wayland;
RGFW_api.window_hide = RGFW_window_hide_Wayland;
- RGFW_api.window_show = RGFW_window_show_Wayland;
+ RGFW_api.window_show = RGFW_window_showPlatform_Wayland;
RGFW_api.window_flash = RGFW_window_flash_X11;
RGFW_api.readClipboardPtr = RGFW_readClipboardPtr_Wayland;
RGFW_api.writeClipboard = RGFW_writeClipboard_Wayland;
@@ -15929,10 +17136,12 @@ void RGFW_load_Wayland(void) {
#ifdef RGFW_OPENGL
RGFW_api.extensionSupportedPlatform_OpenGL = RGFW_extensionSupportedPlatform_OpenGL_Wayland;
RGFW_api.getProcAddress_OpenGL = RGFW_getProcAddress_OpenGL_Wayland;
- RGFW_api.window_createContextPtr_OpenGL = RGFW_window_createContextPtr_OpenGL_Wayland;
- RGFW_api.window_deleteContextPtr_OpenGL = RGFW_window_deleteContextPtr_OpenGL_Wayland;
+ RGFW_api.createContextPtr_OpenGL = RGFW_createContextPtr_OpenGL_Wayland;
+ RGFW_api.deleteContextPtr_OpenGL = RGFW_deleteContextPtr_OpenGL_Wayland;
RGFW_api.window_makeCurrentContext_OpenGL = RGFW_window_makeCurrentContext_OpenGL_Wayland;
RGFW_api.getCurrentContext_OpenGL = RGFW_getCurrentContext_OpenGL_Wayland;
+ RGFW_api.getCurrentSurface_OpenGL = RGFW_getCurrentSurface_OpenGL_Wayland;
+ RGFW_api.window_setContext_OpenGL = RGFW_window_setContext_OpenGL_Wayland;
RGFW_api.window_swapBuffers_OpenGL = RGFW_window_swapBuffers_OpenGL_Wayland;
RGFW_api.window_swapInterval_OpenGL = RGFW_window_swapInterval_OpenGL_Wayland;
#endif
diff --git a/rgfw.c3l/manifest.json b/rgfw.c3l/manifest.json
index baf5ccd..01e1a1a 100644
--- a/rgfw.c3l/manifest.json
+++ b/rgfw.c3l/manifest.json
@@ -1,11 +1,17 @@
{
// features:
- // OPENGL - OpenGL helper functions and data structures
- // EGL - EGL helper functions and data structures
+ // DIRECTX
+ // EGL
+ // MACOS
+ // OPENGL
+ // WGPU
"provides": "rgfw",
"targets": {
"linux-x64": {
"sources": [ "rgfw.c3" ],
},
+ "openbsd-x64": {
+ "sources": [ "rgfw.c3" ],
+ },
},
}
diff --git a/rgfw.c3l/rgfw.c3 b/rgfw.c3l/rgfw.c3
index 66bcd69..4ed2a7b 100644
--- a/rgfw.c3l/rgfw.c3
+++ b/rgfw.c3l/rgfw.c3
@@ -1,18 +1,33 @@
/**
-* Copyright (C) 2026 andromeda
-*
-* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
+ * Copyright (C) 2026 andromeda <andromeda@galaxious.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
**/
module rgfw;
-alias Info = void;
-alias Window = void;
-alias Window_src = void;
+bitstruct InitFlags : char
+{
+ bool opengl : 0;
+ bool egl : 1;
+ bool vulkan : 2;
+ bool x11 : 3;
+}
+
+typedef Info = void;
+typedef Window = void;
+typedef Window_src = void;
constdef Format : char
{
@@ -36,8 +51,8 @@ struct ColorLayout
alias ConvertImageDataFunc = fn void(char*, char*, ColorLayout*, ColorLayout*, usz);
-alias NativeImage = void;
-alias Surface = void;
+typedef NativeImage = void;
+typedef Surface = void;
struct GammaRamp
{
@@ -51,25 +66,25 @@ struct MonitorMode
{
int w;
int h;
- float refreshRate;
+ float refresh_rate;
char red;
char blue;
char green;
void* src;
}
-alias MonitorNode = void;
+typedef MonitorNode = void;
struct Monitor
{
int x;
int y;
- CChar* name;
- float scaleX;
- float scaleY;
- float pixelRatio;
- float physW;
- float physH;
+ CChar[128] name;
+ float scale_x;
+ float scale_y;
+ float pixel_ratio;
+ float phys_w;
+ float phys_h;
MonitorMode mode;
void* userPtr;
MonitorNode* node;
@@ -83,9 +98,9 @@ constdef ModeRequest : char
ALL = SCALE | REFRESH | RGB,
}
-alias Mouse = void;
+typedef Mouse = void;
-constdef Key
+constdef Key : char
{
KEY_NULL = 0,
KEY_ESCAPE = 27,
@@ -194,7 +209,7 @@ constdef Key
KEY_PADMINUS,
KEY_PADEQUAL,
KEY_PADEQUALS = KEY_PADEQUAL,
- KEY_KEY_PAD1,
+ KEY_PAD1,
KEY_PAD2,
KEY_PAD3,
KEY_PAD4,
@@ -211,7 +226,7 @@ constdef Key
KEY_PAUSE,
KEY_WORLD1,
KEY_WORLD2,
- KEY_LAST = 256,
+ KEY_LAST = 255,
}
constdef MouseButton : char
@@ -227,23 +242,23 @@ constdef MouseButton : char
FINAL,
}
-constdef Keymod : char
+bitstruct Keymod : char
{
- CAPSLOCK = 1 << 0,
- NUMLOCK = 1 << 1,
- CONTROL = 1 << 2,
- ALT = 1 << 3,
- SHIFT = 1 << 4,
- SUPER = 1 << 5,
- SCROLLLOCK = 1 << 6,
+ bool caps_lock : 0;
+ bool num_lock : 1;
+ bool control : 2;
+ bool alt : 3;
+ bool shift : 4;
+ bool super : 5;
+ bool scroll_lock : 6;
}
constdef DndActionType : char
{
- ACTION_NONE = 0,
- ACTION_ENTER,
- ACTION_MOVE,
- ACTION_EXIT,
+ NONE = 0,
+ ENTER,
+ MOVE,
+ EXIT,
}
constdef DataTransferType : char
@@ -256,6 +271,13 @@ constdef DataTransferType : char
UNKNOWN,
}
+struct DataTransfer
+{
+ ZString data;
+ usz length;
+ DataTransferType type;
+}
+
struct DataDropNode
{
ZString data;
@@ -273,7 +295,7 @@ constdef EventType : char
MOUSE_BUTTON_PRESSED,
MOUSE_BUTTON_RELEASED,
MOUSE_SCROLL,
- MOUSE_POS_CHANGED,
+ MOUSE_MOTION,
MOUSE_RAW_MOTION,
MOUSE_ENTER,
MOUSE_LEAVE,
@@ -294,46 +316,56 @@ constdef EventType : char
EVENT_COUNT,
}
-constdef EventFlag : uint
+bitstruct EventFlag : uint @overlap
{
- KEY_PRESSED = 1 << (char)EventType.KEY_PRESSED,
- KEY_RELEASED = 1 << (char)EventType.KEY_RELEASED,
- KEY_CHAR = 1 << (char)EventType.KEY_CHAR,
- MOUSE_BUTTON_PRESSED = 1 << (char)EventType.MOUSE_BUTTON_PRESSED,
- MOUSE_BUTTON_RELEASED = 1 << (char)EventType.MOUSE_BUTTON_RELEASED,
- MOUSE_SCROLL = 1 << (char)EventType.MOUSE_SCROLL,
- MOUSE_POS_CHANGED = 1 << (char)EventType.MOUSE_POS_CHANGED,
- MOUSE_RAW_MOTION = 1 << (char)EventType.MOUSE_RAW_MOTION,
- MOUSE_ENTER = 1 << (char)EventType.MOUSE_ENTER,
- MOUSE_LEAVE = 1 << (char)EventType.MOUSE_LEAVE,
- WINDOW_MOVED = 1 << (char)EventType.WINDOW_MOVED,
- WINDOW_RESIZED = 1 << (char)EventType.WINDOW_RESIZED,
- WINDOW_FOCUS_IN = 1 << (char)EventType.WINDOW_FOCUS_IN,
- WINDOW_FOCUS_OUT = 1 << (char)EventType.WINDOW_FOCUS_OUT,
- WINDOW_REFRESH = 1 << (char)EventType.WINDOW_REFRESH,
- WINDOW_CLOSE = 1 << (char)EventType.WINDOW_CLOSE,
- WINDOW_MAXIMIZED = 1 << (char)EventType.WINDOW_MAXIMIZED,
- WINDOW_MINIMIZED = 1 << (char)EventType.WINDOW_MINIMIZED,
- WINDOW_RESTORED = 1 << (char)EventType.WINDOW_RESTORED,
- DATA_DROP = 1 << (char)EventType.DATA_DROP,
- DATA_DRAG = 1 << (char)EventType.DATA_DRAG,
- SCALE_UPDATED = 1 << (char)EventType.SCALE_UPDATED,
- MONITOR_CONNECTED = 1 << (char)EventType.MONITOR_CONNECTED,
- MONITOR_DISCONNECTED = 1 << (char)EventType.MONITOR_DISCONNECTED,
-
- KEY_EVENTS = KEY_PRESSED | KEY_RELEASED | KEY_CHAR,
- MOUSE_EVENTS = MOUSE_BUTTON_PRESSED | MOUSE_BUTTON_RELEASED | MOUSE_SCROLL | MOUSE_POS_CHANGED | MOUSE_RAW_MOTION
- | MOUSE_ENTER
- | MOUSE_LEAVE,
- WINDOW_EVENTS = WINDOW_MOVED | WINDOW_RESIZED | WINDOW_REFRESH | WINDOW_MAXIMIZED | WINDOW_MINIMIZED | WINDOW_RESTORED
- | SCALE_UPDATED,
- WINDOW_FOCUS_EVENTS = WINDOW_FOCUS_IN | WINDOW_FOCUS_OUT,
- DATA_DRAG_DROP_EVENTS = DATA_DRAG | DATA_DROP,
- MONITOR_EVENTS = MONITOR_CONNECTED | MONITOR_DISCONNECTED,
- ALL_EVENTS = KEY_EVENTS | MOUSE_EVENTS | WINDOW_EVENTS | WINDOW_FOCUS_EVENTS | DATA_DRAG_DROP_EVENTS
- | MONITOR_EVENTS,
+ bool key_pressed : (char)EventType.KEY_PRESSED;
+ bool key_released : (char)EventType.KEY_RELEASED;
+ bool key_char : (char)EventType.KEY_CHAR;
+ bool mouse_scroll : (char)EventType.MOUSE_SCROLL;
+ bool mouse_button_pressed : (char)EventType.MOUSE_BUTTON_PRESSED;
+ bool mouse_button_released : (char)EventType.MOUSE_BUTTON_RELEASED;
+ bool mouse_motion : (char)EventType.MOUSE_MOTION;
+ bool mouse_raw_motion : (char)EventType.MOUSE_RAW_MOTION;
+ bool mouse_enter : (char)EventType.MOUSE_ENTER;
+ bool mouse_leave : (char)EventType.MOUSE_LEAVE;
+ bool window_moved : (char)EventType.WINDOW_MOVED;
+ bool window_resized : (char)EventType.WINDOW_RESIZED;
+ bool window_focus_in : (char)EventType.WINDOW_FOCUS_IN;
+ bool window_focus_out : (char)EventType.WINDOW_FOCUS_OUT;
+ bool window_refresh : (char)EventType.WINDOW_REFRESH;
+ bool window_maximized : (char)EventType.WINDOW_MAXIMIZED;
+ bool window_minimized : (char)EventType.WINDOW_MINIMIZED;
+ bool window_restored : (char)EventType.WINDOW_RESTORED;
+ bool scale_updated : (char)EventType.SCALE_UPDATED;
+ bool window_close : (char)EventType.WINDOW_CLOSE;
+ bool data_drop : (char)EventType.DATA_DROP;
+ bool data_drag : (char)EventType.DATA_DRAG;
+ bool monitor_connected : (char)EventType.MONITOR_CONNECTED;
+ bool monitor_disconnected : (char)EventType.MONITOR_DISCONNECTED;
+ bool key_events : (char)EventType.KEY_PRESSED | (char)EventType.KEY_RELEASED | (char)EventType.KEY_CHAR;
+ bool mouse_events : (char)EventType.MOUSE_BUTTON_PRESSED | (char)EventType.MOUSE_BUTTON_RELEASED | (char)EventType.MOUSE_MOTION
+ | (char)EventType.MOUSE_ENTER
+ | (char)EventType.MOUSE_LEAVE
+ | (char)EventType.MOUSE_SCROLL
+ | (char)EventType.MOUSE_RAW_MOTION;
+ bool window_events : (char)EventType.WINDOW_MOVED | (char)EventType.WINDOW_RESIZED | (char)EventType.WINDOW_REFRESH
+ | (char)EventType.WINDOW_MAXIMIZED
+ | (char)EventType.WINDOW_RESTORED
+ | (char)EventType.SCALE_UPDATED;
+ bool window_focus_events : (char)EventType.WINDOW_FOCUS_IN | (char)EventType.WINDOW_FOCUS_OUT;
+ bool data_drag_drop_events : (char)EventType.DATA_DROP | (char)EventType.DATA_DRAG;
+ bool monitor_events : (char)EventType.MONITOR_CONNECTED | (char)EventType.MONITOR_DISCONNECTED;
}
+const EventFlag ALL_EVENTS = {
+ .key_events,
+ .mouse_events,
+ .window_events,
+ .window_focus_events,
+ .data_drag_drop_events,
+ .monitor_events
+};
+
struct CommonEvent
{
EventType type;
@@ -342,31 +374,27 @@ struct CommonEvent
struct WindowFocusEvent
{
- EventType type;
- Window* win;
+ inline CommonEvent meta;
bool state;
}
struct MouseButtonEvent
{
- EventType type;
- Window* win;
+ inline CommonEvent meta;
MouseButton value;
bool state;
}
struct MouseDeltaEvent
{
- EventType type;
- Window* win;
+ inline CommonEvent meta;
float x;
float y;
}
struct MousePosEvent
{
- EventType type;
- Window* win;
+ inline CommonEvent meta;
int x;
int y;
bool inWindow;
@@ -374,8 +402,7 @@ struct MousePosEvent
struct KeyEvent
{
- EventType type;
- Window* win;
+ inline CommonEvent meta;
Key value;
bool repeat;
Keymod mod;
@@ -384,22 +411,19 @@ struct KeyEvent
struct KeyCharEvent
{
- EventType type;
- Window* win;
+ inline CommonEvent meta;
Char32 value;
}
struct DataDropEvent
{
- EventType type;
- Window* win;
+ inline CommonEvent meta;
DataDropNode* value;
}
struct DataDragEvent
{
- EventType type;
- Window* win;
+ inline CommonEvent meta;
int x;
int y;
DndActionType action;
@@ -408,24 +432,21 @@ struct DataDragEvent
struct ScaleUpdatedEvent
{
- EventType type;
- Window* win;
+ inline CommonEvent meta;
float x;
float y;
}
struct MonitorEvent
{
- EventType type;
- Window* win;
+ inline CommonEvent meta;
Monitor* monitor;
bool state;
}
struct WindowUpdateEvent
{
- EventType type;
- Window* win;
+ inline CommonEvent meta;
int x;
int y;
int w;
@@ -462,38 +483,44 @@ struct Callbacks
GenericFunc* arr;
}
-constdef WindowFlags : uint
+constdef FullscreenMode : char
+{
+ NONE,
+ BORDERLESS,
+ EXCLUSIVE,
+}
+
+bitstruct WindowFlags : uint @overlap
{
- NO_BORDER = 1 << 0,
- NO_RESIZE = 1 << 1,
- ALLOW_DND = 1 << 2,
- HIDE_MOUSE = 1 << 3,
- FULLSCREEN = 1 << 4,
- TRANSLUCENT = 1 << 5,
- TRANSPARENT = TRANSLUCENT,
- CENTER = 1 << 6,
- RAW_MOUSE = 1 << 7,
- SCALE_TO_MONITOR = 1 << 8,
- HIDE = 1 << 9,
- MAXIMIZE = 1 << 10,
- CENTER_CURSOR = 1 << 11,
- FLOATING = 1 << 12,
- FOCUS_ON_SHOW = 1 << 13,
- MINIMIZE = 1 << 14,
- FOCUS = 1 << 15,
- CAPTURE_MOUSE = 1 << 16,
- OPENGL = 1 << 17,
- EGL = 1 << 18,
- NO_DEINIT_ON_CLOSE = 1 << 19,
- WINDOWED_FULLSCREEN = NO_BORDER | MAXIMIZE,
- CAPTURE_RAW_MOUSE = CAPTURE_MOUSE | RAW_MOUSE,
+ bool no_border : 0;
+ bool no_resize : 1;
+ bool allow_DND : 2;
+ bool hide_mouse : 3;
+ bool fullscreen_exclusive : 4;
+ bool translucent : 5;
+ bool transparent : 5;
+ bool center : 6;
+ bool raw_mouse : 7;
+ bool scale_to_monitor : 8;
+ bool hide : 9;
+ bool maximize : 10;
+ bool center_cursor : 11;
+ bool floating : 12;
+ bool focus_on_show : 13;
+ bool minimize : 14;
+ bool focus : 15;
+ bool capture_mouse : 16;
+ bool openGL : 17;
+ bool egl : 18;
+ bool fullscreen_borderless : 19;
+ bool capture_raw_mouse : 7 | 16;
}
-constdef Icon : char
+bitstruct Icon : char @overlap
{
- TASKBAR = 1 << 0,
- WINDOW = 1 << 1,
- BOTH = TASKBAR | WINDOW,
+ bool taskbar : 0;
+ bool window : 1;
+ bool both : 0 | 1;
}
constdef MouseIcon : char
@@ -552,8 +579,10 @@ constdef ErrorCode : char
ERR_FAILED_FUNC_LOAD,
ERR_BUFFER,
ERR_METAL,
+ ERR_OBJC_RUNTIME,
ERR_PLATFORM,
ERR_EVENT_QUEUE,
+ ERR_NO_INIT,
INFO_WINDOW,
INFO_BUFFER,
INFO_GLOBAL,
@@ -570,31 +599,32 @@ struct DebugInfo
}
alias DebugFunc = fn void(DebugInfo*);
-alias Proc @if($feature(OPENGL)) = fn void();
-alias GlContext @if($feature(OPENGL)) = void;
-alias EglContext @if($feature(EGL)) = void;
+alias Proc = fn void();
+typedef GlContext @feat(OPENGL) = void;
+typedef EglContext @feat(OPENGL) = void;
-constdef GlReleaseBehavior : int @if($feature(OPENGL))
+constdef GlReleaseBehavior : int @feat(OPENGL)
{
FLUSH = 0,
NONE,
}
-constdef GlProfile : int @if($feature(OPENGL))
+constdef GlProfile : int @feat(OPENGL)
{
CORE = 0,
FORWARD_COMPATIBILITY,
COMPATIBILITY,
ES,
+ WEB,
}
-constdef GlRenderer : int @if($feature(OPENGL))
+constdef GlRenderer : int @feat(OPENGL)
{
ACCELERATED = 0,
SOFTWARE,
}
-struct GlHints @if($feature(OPENGL))
+struct GlHints @feat(OPENGL)
{
int stencil;
int samples;
@@ -625,213 +655,267 @@ struct GlHints @if($feature(OPENGL))
extern fn void* alloc(usz) @cname("RGFW_alloc");
extern fn void free(void*) @cname("RGFW_free");
-extern fn usz sizeofWindow() @cname("RGFW_sizeofWindow");
-extern fn usz sizeofWindowSrc() @cname("RGFW_sizeofWindowSrc");
-extern fn void useWayland(bool) @cname("RGFW_useWayland");
-extern fn bool usingWayland() @cname("RGFW_usingWayland");
-extern fn void* getLayer_OSX() @cname("RGFW_getLayer_OSX");
-extern fn void* getDisplay_X11() @cname("RGFW_getDisplay_X11");
-extern fn void* getDisplay_Wayland() @cname("RGFW_getDisplay_Wayland"); // TODO return isn't void*
-extern fn void setClassName(ZString) @cname("RGFW_setClassName");
-extern fn void setXInstName(ZString) @cname("RGFW_setXInstName");
-extern fn void moveToMacOSResourceDir() @cname("RGFW_modeToMacOSResourceDir");
-extern fn void copyImageData(char*, int, int, Format, char*, Format, ConvertImageDataFunc) @cname("RGFW_copyImageData");
-extern fn usz sizeofNativeImage() @cname("RGFW_sizeofNativeImage");
-extern fn usz sizeofSurface() @cname("RGFW_sizeofSurface");
-extern fn Format nativeFormat() @cname("RGFW_nativeFormat");
-extern fn Surface* createSurface(char*, int, int, Format) @cname("RGFW_createSurface");
-extern fn bool createSurfacePtr(char*, int, int, Format, Surface*) @cname("RGFW_createSurfacePtr");
-extern fn NativeImage* surface_getNativeImage(Surface*) @cname("RGFW_surface_getNativeImage");
-extern fn void surface_free(Surface*) @cname("RGFW_surface_free");
-extern fn void surface_freePtr(Surface*) @cname("RGFW_surface_freePtr");
-extern fn Mouse* createMouse(char*, int, int, Format) @cname("RGFW_createMouse");
-extern fn Mouse* createMouseStandard(MouseIcon) @cname("RGFW_createMouseStandard");
-extern fn void freeMouse(Mouse*) @cname("RGFW_freeMouse");
-extern fn MonitorMode* monitor_getModes(Monitor*, usz*) @cname("RGFW_monitor_getModes");
-extern fn void freeModes(MonitorMode*) @cname("RGFW_freeModes");
-extern fn usz monitor_getModesPtr(Monitor*, MonitorMode**) @cname("RGFW_monitor_getModesPtr");
-extern fn bool monitor_findClosestMode(Monitor*, MonitorMode*, MonitorMode*) @cname("RGFW_monitor_findClosestMode");
-extern fn GammaRamp* monitor_getGammaRamp(Monitor*) @cname("RGFW_monitor_getGammaRamp");
-extern fn void freeGammaRamp(GammaRamp*) @cname("RGFW_freeGammaRamp");
-extern fn usz monitor_getGammaRampPtr(Monitor*, GammaRamp*) @cname("RGFW_monitor_getGammaRampPtr");
-extern fn bool monitor_setGammaRamp(Monitor*, GammaRamp*) @cname("RGFW_monitor_setGammaRamp");
-extern fn bool monitor_setGamma(Monitor*, float) @cname("RGFW_monitor_setGamma");
-extern fn bool monitor_setGammaPtr(Monitor*, float, ushort*, usz) @cname("RGFW_monitor_setGammaPtr");
-extern fn bool monitor_getWorkarea(Monitor*, int*, int*, int*, int*) @cname("RGFW_monitor_getWorkarea");
-extern fn bool monitor_getPosition(Monitor*, int*, int*) @cname("RGFW_monitor_getPosition");
-extern fn ZString monitor_getName(Monitor*) @cname("RGFW_monitor_getName");
-extern fn bool monitor_getScale(Monitor*, float*, float*) @cname("RGFW_monitor_getScale");
-extern fn bool monitor_getPhysicalSize(Monitor*, float*, float*) @cname("RGFW_monitor_getPhysicalSize");
-extern fn void monitor_setUserPtr(Monitor*, void*) @cname("RGFW_monitor_setUserPtr");
-extern fn void* monitor_getUserPtr(Monitor*) @cname("RGFW_monitor_getUserPtr");
-extern fn bool monitor_getMode(Monitor*, MonitorMode*) @cname("RGFW_monitor_getMode");
-extern fn void pollMonitors() @cname("RGFW_pollMonitors");
-extern fn Monitor** getMonitors(usz*) @cname("RGFW_getMonitors");
-extern fn Monitor* getPrimaryMonitor() @cname("RGFW_getPrimaryMonitor");
-extern fn bool monitor_requestMode(Monitor*, MonitorMode*, ModeRequest) @cname("RGFW_monitor_requestMode");
-extern fn bool monitor_setMode(Monitor*, MonitorMode*) @cname("RGFW_monitor_setMode");
-extern fn bool monitorModeCompare(MonitorMode*, MonitorMode*, ModeRequest) @cname("RGFW_monitorModeCompare");
-extern fn bool monitor_scaleToWindow(Monitor*, Window*) @cname("RGFW_monitor_scaleToWindow");
-extern fn void setRawMouseMode(bool) @cname("RGFW_setRawMouseMode");
-extern fn void setBuildDND(bool) @cname("RGFW_setbuildDND");
-extern fn void waitForEvent(int) @cname("RGFW_waitForEvent");
-extern fn void setQueueEvents(bool) @cname("RGFW_setQueueEvents");
-extern fn GenericFunc* setEventCallback(EventType, GenericFunc) @cname("RGFW_setEventCallback");
-extern fn void setDualEventCallback(EventType, GenericFunc, GenericFunc*, GenericFunc*) @cname("RGFW_setDualEventCallback");
-extern fn void setAllEventCallbacks(GenericFunc, Callbacks*) @cname("RGFW_setAllEventCallbacks");
-extern fn void pollEvents() @cname("RGFW_pollEvents");
-extern fn void stopCheckEvents() @cname("RGFW_stopCheckEvents");
-extern fn bool checkEvent(Event*) @cname("RGFW_checkEvent");
-extern fn bool checkQueuedEvent(Event*) @cname("RGFW_checkQueuedEvent");
-extern fn bool isKeyPressed(Key) @cname("RGFW_isKeyPressed");
-extern fn bool isKeyReleased(Key) @cname("RGFW_isKeyReleased");
-extern fn bool isKeyDown(Key) @cname("RGFW_isKeyDown");
-extern fn bool isMousePressed(MouseButton) @cname("RGFW_isMousePressed");
-extern fn bool isMouseReleased(MouseButton) @cname("RGFW_isMouseReleased");
-extern fn bool isMouseDown(MouseButton) @cname("RGFW_isMouseDown");
-extern fn void getMouseScroll(float*, float*) @cname("RGFW_getMouseScroll");
-extern fn void getMouseVector(float*, float*) @cname("RGFW_getMouseVector");
-extern fn Window* createWindow(ZString, int, int, int, int, WindowFlags) @cname("RGFW_createWindow");
-extern fn Window* createWindowPtr(ZString, int, int, int, int, WindowFlags, Window*) @cname("RGFW_createWindowPtr");
-extern fn Surface* window_createSurface(Window*, char*, int, int, Format) @cname("RGFW_window_createSurface");
-extern fn Surface* window_createSurfacePtr(Window*, char*, int, int, Format, Surface*) @cname("RGFW_window_createSurfacePtr");
-extern fn void surface_setConvertFunc(Surface*, ConvertImageDataFunc) @cname("RGFW_surface_setConvertFunc");
-extern fn void window_blitSurface(Window*, Surface*) @cname("RGFW_window_blitSurface");
-extern fn bool window_getPosition(Window*, int*, int*) @cname("RGFW_window_getPosition");
-extern fn bool window_getSize(Window*, int*, int*) @cname("RGFW_window_getSize");
-extern fn bool window_getSizeInPixels(Window*, int*, int*) @cname("RGFW_window_getSizeInPixels");
-extern fn uint window_getFlags(Window*) @cname("RGFW_window_getFlags");
-extern fn Key window_getExitKey(Window*) @cname("RGFW_window_getExitKey");
-extern fn void window_setExitKey(Window*, Key) @cname("RGFW_window_setExitKey");
-extern fn void window_setEnabledEvents(Window*, EventFlag) @cname("RGFW_window_setEnabledEvents");
-extern fn EventFlag window_getEnabledEvents(Window*) @cname("RGFW_window_getEnabledEvents");
-extern fn void window_setDisabledEvents(Window*, EventFlag) @cname("RGFW_window_setDisabledEvents");
-extern fn void window_setEventState(Window*, EventFlag, bool) @cname("RGFW_window_setEventState");
-extern fn void* window_getUserPtr(Window*) @cname("RGFW_window_getUserPtr");
-extern fn void window_setUserPtr(Window*, void*) @cname("RGFW_window_setUserPtr");
-extern fn Window_src* window_getSrc(Window*) @cname("RGFW_window_getSrc");
-extern fn void window_setLayer_OSX(Window*, void*) @cname("RGFW_window_setLayer_OSX");
-extern fn void* window_getView_OSX(Window*) @cname("RGFW_window_getView_OSX");
-extern fn void* window_getWindow_OSX(Window*) @cname("RGFW_window_getWindow_OSX");
-extern fn void* window_getHWND(Window*) @cname("RGFW_window_getHWND");
-extern fn void* window_getHDC(Window*) @cname("RGFW_window_getHDC");
-extern fn ulong window_getWindow_X11(Window*) @cname("RGFW_window_getWindow_X11");
-extern fn void* window_getWindow_Wayland(Window*) @cname("RGFW_window_getWindow_Wayland"); // TODO return isn't *void
-extern fn void window_setFlags(Window*, WindowFlags) @cname("RGFW_window_setFlags");
-extern fn bool window_checkEvent(Window*, Event*) @cname("RGFW_window_checkEvent");
-extern fn bool window_checkQueuedEvent(Window*, Event*) @cname("RGFW_window_checkQueuedEvent");
-extern fn bool window_isKeyPressed(Window*, Key) @cname("RGFW_window_isKeyPressed");
-extern fn bool window_isKeyDown(Window*, Key) @cname("RGFW_window_isKeyDown");
-extern fn bool window_isKeyReleased(Window*, Key) @cname("RGFW_window_isKeyReleased");
-extern fn bool window_isMousePressed(Window*, MouseButton) @cname("RGFW_window_isMousePressed");
-extern fn bool window_isMouseDown(Window*, MouseButton) @cname("RGFW_window_isMouseDown");
-extern fn bool window_isMouseReleased(Window*, MouseButton) @cname("RGFW_window_isMouseReleased");
-extern fn bool window_didMouseLeave(Window*) @cname("RGFW_window_didMouseLeave");
-extern fn bool window_didMouseEnter(Window*) @cname("RGFW_window_didMouseEnter");
-extern fn bool window_isMouseInside(Window*) @cname("RGFW_window_isMouseInside");
-extern fn bool window_isDataDragging(Window*) @cname("RGFW_window_isDataDragging");
-extern fn bool window_getDataDrag(Window*, int*, int*) @cname("RGFW_window_getDataDrag");
-extern fn bool window_didDataDrop(Window*) @cname("RGFW_window_didDataDrop");
-extern fn DataDropNode* window_getDataDrop(Window*) @cname("RGFW_window_getDataDrop");
-extern fn void window_close(Window*) @cname("RGFW_window_close");
-extern fn void window_closePtr(Window*) @cname("RGFW_window_closePtr");
-extern fn bool window_fetchSize(Window*, int*, int*) @cname("RGFW_window_fetchSize");
-extern fn void window_move(Window*, int, int) @cname("RGFW_window_move");
-extern fn void window_moveToMonitor(Window*, Monitor*) @cname("RGFW_window_moveToMonitor");
-extern fn void window_resize(Window*, int, int) @cname("RGFW_window_resize");
-extern fn void window_setAspectRatio(Window*, int, int) @cname("RGFW_window_setAspectRation");
-extern fn void window_setMinSize(Window*, int, int) @cname("RGFW_window_setMinSize");
-extern fn void window_setMaxSize(Window*, int, int) @cname("RGFW_window_setMaxSize");
-extern fn void window_focus(Window*) @cname("RGFW_window_focus");
-extern fn bool window_isInFocus(Window*) @cname("RGFW_window_isInFocus");
-extern fn void window_raise(Window*) @cname("RGFW_window_raise");
-extern fn void window_maximize(Window*) @cname("RGFW_window_maximize");
-extern fn void window_setFullscreen(Window*, bool) @cname("RGFW_window_setFullscreen");
-extern fn void window_center(Window*) @cname("RGFW_window_center");
-extern fn void window_minimize(Window*) @cname("RGFW_window_minimize");
-extern fn void window_restore(Window*) @cname("RGFW_window_restore");
-extern fn void window_setFloating(Window*, bool) @cname("RGFW_window_setFloating");
-extern fn void window_setOpacity(Window*, char) @cname("RGFW_window_setOpacity");
-extern fn void window_setBorder(Window*, bool) @cname("RGFW_window_setBorder");
-extern fn bool window_borderless(Window*) @cname("RGFW_window_borderless");
-extern fn void window_setDND(Window*, bool) @cname("RGFW_window_setDND");
-extern fn bool window_allowsDND(Window*) @cname("RGFW_window_allowsDND");
-extern fn void window_setMousePassthrough(Window*, bool) @cname("RGFW_window_setMousePassthrough");
-extern fn void window_setName(Window*, ZString) @cname("RGFW_window_setName");
-extern fn bool window_setIcon(Window*, char*, int, int, Format) @cname("RGFW_window_seticon");
-extern fn bool window_setIconEx(Window*, char*, int, int, Format, Icon) @cname("RGFW_window_setIconEx");
-extern fn bool window_setMouse(Window*, Mouse*) @cname("RGFW_window_setMouse");
-extern fn bool window_setMouseStandard(Window*, MouseIcon) @cname("RGFW_window_setMouseStandard");
-extern fn bool window_setMouseDefault(Window*) @cname("RGFW_window_setMouseDefault");
-extern fn void window_setRawMouseMode(Window*, bool) @cname("RGFW_window_setRawMousemode");
-extern fn void window_captureMouse(Window*, bool) @cname("RGFW_window_captureMouse");
-extern fn void window_captureRawMouse(Window*, bool) @cname("RGFW_window_captureRawMouse");
-extern fn bool window_isRawMouseMode(Window*) @cname("RGFW_window_isRawMouseMode");
-extern fn bool window_isCaptured(Window*) @cname("RGFW_window_isCaptured");
-extern fn void window_hide(Window*) @cname("RGFW_window_hide");
-extern fn void window_show(Window*) @cname("RGFW_window_show");
-extern fn void window_flash(Window*, FlashRequest) @cname("RGFW_window_flash");
-extern fn void window_setShouldClose(Window*, bool) @cname("RGFW_window_setShouldClose");
-extern fn bool window_getGlobalMouse(int*, int*) @cname("RGFW_window_getGlobalMouse");
-extern fn bool window_getMouse(Window*, int*, int*) @cname("RGFW_window_getMouse");
-extern fn void window_showMouse(Window*, bool) @cname("RGFW_window_showMouse");
-extern fn bool window_isMouseHidden(Window*) @cname("RGFW_window_isMouseHidden");
-extern fn void window_moveMouse(Window*, int, int) @cname("RGFW_window_moveMouse");
-extern fn bool window_shouldClose(Window*) @cname("RGFW_window_shouldClose");
-extern fn bool window_isFullscreen(Window*) @cname("RGFW_window_isFullscreen");
-extern fn bool window_isHidden(Window*) @cname("RGFW_window_isHidden");
-extern fn bool window_isMinimized(Window*) @cname("RGFW_window_isMinimized");
-extern fn bool window_isMaximized(Window*) @cname("RGFW_window_isMaximized");
-extern fn bool window_isFloating(Window*) @cname("RGFW_window_isFloating");
-extern fn void window_scaleToMonitor(Window*) @cname("RGFW_window_scaleToMonitor");
-extern fn Monitor* window_getMonitor(Window*) @cname("RGFW_window_getMonitor");
-extern fn ZString readClipboard(usz*) @cname("RGFW_readClipboard");
-extern fn sz readClipboardPtr(CChar*, usz) @cname("RGFW_readClipboardPtr");
-extern fn void writeClipboard(ZString, uint) @cname("RGFW_writeClipboard");
-extern fn DebugFunc setDebugCallback(DebugFunc) @cname("RGFW_setDebugCallback");
-extern fn void debugCallback(DebugType, ErrorCode, ZString) @cname("RGFW_debugCallback");
+extern fn usz sizeof_info() @cname("RGFW_sizeofInfo");
+extern fn int init(ZString, InitFlags) @cname("RGFW_init");
+extern fn void deinit() @cname("RGFW_deinit");
+extern fn int init_ptr(ZString, InitFlags, Info*) @cname("RGFW_init_ptr");
+extern fn void deinit_ptr(Info*) @cname("RGFW_deinit_ptr");
+extern fn void set_info(Info*) @cname("RGFW_setInfo");
+extern fn Info* get_info() @cname("RGFW_getInfo");
+extern fn usz sizeof_window() @cname("RGFW_sizeofWindow");
+extern fn usz sizeof_window_src() @cname("RGFW_sizeofWindowSrc");
+extern fn bool using_wayland() @cname("RGFW_usingWayland");
+extern fn void* get_layer_OSX() @cname("RGFW_getLayer_OSX");
+extern fn void* get_display_X11() @cname("RGFW_getDisplay_X11");
+extern fn void* get_display_wayland() @cname("RGFW_getDisplay_Wayland");
+extern fn void move_to_macos_resource_dir() @cname("RGFW_moveToMacOSResourceDir");
+extern fn void copy_image_data(char*, int, int, Format, char*, Format, ConvertImageDataFunc) @cname("RGFW_copyImageData");
+extern fn usz sizeof_native_image() @cname("RGFW_sizeofNativeImage");
+extern fn usz sizeof_surface() @cname("RGFW_sizeofSurface");
+extern fn Format native_format() @cname("RGFW_nativeFormat");
+extern fn Surface* create_surface(char*, int, int, Format) @cname("RGFW_createSurface");
+extern fn bool create_surface_ptr(char*, int, int, Format, Surface*) @cname("RGFW_createSurfacePtr");
+extern fn NativeImage* Surface.get_native_image(&self) @cname("RGFW_surface_getNativeImage");
+extern fn void Surface.free(&self) @cname("RGFW_surface_free");
+extern fn void Surface.free_ptr(&self) @cname("RGFW_surface_freePtr");
+extern fn Mouse* create_mouse(char*, int, int, Format) @cname("RGFW_createMouse");
+extern fn Mouse* create_mouse_standard(MouseIcon) @cname("RGFW_createMouseStandard");
+extern fn void Mouse.free(Mouse*) @cname("RGFW_freeMouse");
+extern fn MonitorMode* Monitor.get_modes(&self, usz*) @cname("RGFW_monitor_getModes");
+extern fn void free_modes(MonitorMode*) @cname("RGFW_freeModes");
+extern fn usz Monitor.get_modes_ptr(&self, MonitorMode**) @cname("RGFW_monitor_getModesPtr");
+extern fn bool Monitor.find_closest_mode(&self, MonitorMode*, MonitorMode*) @cname("RGFW_monitor_findClosestMode");
+extern fn GammaRamp* Monitor.get_gamma_ramp(&self) @cname("RGFW_monitor_getGammaRamp");
+extern fn void GammaRamp.free(&self) @cname("RGFW_freeGammaRamp");
+extern fn usz Monitor.get_gamma_ramp_ptr(&self, GammaRamp*) @cname("RGFW_monitor_getGammaRampPtr");
+extern fn bool Monitor.set_gamma_ramp(&self, GammaRamp*) @cname("RGFW_monitor_setGammaRamp");
+extern fn bool Monitor.set_gamma(&self, float) @cname("RGFW_monitor_setGamma");
+extern fn bool Monitor.set_gamma_ptr(&self, float, ushort*, usz) @cname("RGFW_monitor_setGammaPtr");
+extern fn bool Monitor.get_workarea(&self, int*, int*, int*, int*) @cname("RGFW_monitor_getWorkarea");
+extern fn bool Monitor.get_position(&self, int*, int*) @cname("RGFW_monitor_getPosition");
+extern fn ZString Monitor.get_name(&self) @cname("RGFW_monitor_getName");
+extern fn bool Monitor.get_scale(&self, float*, float*) @cname("RGFW_monitor_getScale");
+extern fn bool Monitor.get_physical_size(&self, float*, float*) @cname("RGFW_monitor_getPhysicalSize");
+extern fn void Monitor.set_user_ptr(&self, void*) @cname("RGFW_monitor_setUserPtr");
+extern fn void* Monitor.get_user_ptr(&self) @cname("RGFW_monitor_getUserPtr");
+extern fn bool Monitor.get_mode(&self, MonitorMode*) @cname("RGFW_monitor_getMode");
+extern fn void poll_monitors() @cname("RGFW_pollMonitors");
+extern fn void free_monitors() @cname("RGFW_freeMonitors");
+extern fn Monitor** get_monitors(usz*) @cname("RGFW_getMonitors");
+extern fn bool get_monitors_ptr(usz, Monitor**, usz*) @cname("RGFW_getMonitorsPtr");
+extern fn Monitor* get_primary_monitor() @cname("RGFW_getPrimaryMonitor");
+extern fn bool Monitor.request_mode(&self, MonitorMode*, ModeRequest) @cname("RGFW_monitor_requestMode");
+extern fn bool Monitor.set_mode(&self, MonitorMode*) @cname("RGFW_monitor_setMode");
+extern fn bool monitor_mode_compare(MonitorMode*, MonitorMode*, ModeRequest) @cname("RGFW_monitorModeCompare");
+extern fn bool Monitor.scale_to_window(&self, Window*) @cname("RGFW_monitor_scaleToWindow");
+extern fn void set_raw_mouse_mode(bool) @cname("RGFW_setRawMouseMode");
+extern fn void set_build_DND(bool) @cname("RGFW_setbuildDND");
+extern fn void wait_for_event(int) @cname("RGFW_waitForEvent");
+extern fn void set_queue_events(bool) @cname("RGFW_setQueueEvents");
+extern fn GenericFunc* set_event_callback(EventType, GenericFunc) @cname("RGFW_setEventCallback");
+extern fn void set_dual_event_callback(EventType, GenericFunc, GenericFunc*, GenericFunc*) @cname("RGFW_setDualEventCallback");
+extern fn void set_all_event_callbacks(GenericFunc, Callbacks*) @cname("RGFW_setAllEventCallbacks");
+extern fn void poll_events() @cname("RGFW_pollEvents");
+extern fn void stop_check_events() @cname("RGFW_stopCheckEvents");
+extern fn bool check_event(Event*) @cname("RGFW_checkEvent");
+extern fn bool check_queued_event(Event*) @cname("RGFW_checkQueuedEvent");
+extern fn bool Key.is_pressed(self) @cname("RGFW_isKeyPressed");
+extern fn bool Key.is_released(self) @cname("RGFW_isKeyReleased");
+extern fn bool Key.is_down(self) @cname("RGFW_isKeyDown");
+extern fn bool MouseButton.is_pressed(self) @cname("RGFW_isMousePressed");
+extern fn bool MouseButton.is_released(self) @cname("RGFW_isMouseReleased");
+extern fn bool MouseButton.is_down(self) @cname("RGFW_isMouseDown");
+extern fn void get_mouse_scroll(float*, float*) @cname("RGFW_getMouseScroll");
+extern fn void get_mouse_vector(float*, float*) @cname("RGFW_getMouseVector");
+extern fn Window* create_window(ZString, int, int, int, int, WindowFlags) @cname("RGFW_createWindow");
+extern fn Window* create_window_ptr(ZString, int, int, int, int, WindowFlags, Window*) @cname("RGFW_createWindowPtr");
+extern fn Surface* Window.create_surface(&self, char*, int, int, Format) @cname("RGFW_window_createSurface");
+extern fn Surface* Window.create_surface_ptr(&self, char*, int, int, Format, Surface*) @cname("RGFW_window_createSurfacePtr");
+extern fn void Surface.set_convert_func(&self, ConvertImageDataFunc) @cname("RGFW_surface_setConvertFunc");
+extern fn void Window.blit_suface(&self, Surface*) @cname("RGFW_window_blitSurface");
+extern fn bool Window.get_position(&self, int*, int*) @cname("RGFW_window_getPosition");
+extern fn bool Window.get_size(&self, int*, int*) @cname("RGFW_window_getSize");
+extern fn bool Window.get_size_in_pixels(&self, int*, int*) @cname("RGFW_window_getSizeInPixels");
+extern fn uint Window.get_flags(&self) @cname("RGFW_window_getFlags");
+extern fn Key Window.get_exit_key(&self) @cname("RGFW_window_getExitKey");
+extern fn void Window.set_exit_key(&self, Key) @cname("RGFW_window_setExitKey");
+extern fn void Window.set_enabled_events(&self, EventFlag) @cname("RGFW_window_setEnabledEvents");
+extern fn EventFlag Window.get_enabled_events(&self) @cname("RGFW_window_getEnabledEvents");
+extern fn void Window.set_disabled_events(&self, EventFlag) @cname("RGFW_window_setDisabledEvents");
+extern fn void Window.set_event_state(&self, EventFlag, bool) @cname("RGFW_window_setEventState");
+extern fn void* Window.get_user_ptr(&self) @cname("RGFW_window_getUserPtr");
+extern fn void Window.set_user_ptr(&self, void*) @cname("RGFW_window_setUserPtr");
+extern fn Window_src* Window.get_src(&self) @cname("RGFW_window_getSrc");
+extern fn void Window.set_layer_OSX(&self, void*) @cname("RGFW_window_setLayer_OSX");
+extern fn void* Window.get_view_OSX(&self) @cname("RGFW_window_getView_OSX");
+extern fn void* Window.get_window_OSX(&self) @cname("RGFW_window_getWindow_OSX");
+extern fn void* Window.get_HWND(&self) @cname("RGFW_window_getHWND");
+extern fn void* Window.get_HDC(&self) @cname("RGFW_window_getHDC");
+extern fn ulong Window.get_window_X11(&self) @cname("RGFW_window_getWindow_X11");
+extern fn void* Window.get_window_wayland(&self) @cname("RGFW_window_getWindow_Wayland");
+extern fn void Window.set_flags(&self, WindowFlags) @cname("RGFW_window_setFlags");
+extern fn bool Window.check_event(&self, Event*) @cname("RGFW_window_checkEvent");
+extern fn bool Window.check_queued_event(&self, Event*) @cname("RGFW_window_checkQueuedEvent");
+extern fn bool Window.is_key_pressed(&self, Key) @cname("RGFW_window_isKeyPressed");
+extern fn bool Window.is_key_down(&self, Key) @cname("RGFW_window_isKeyDown");
+extern fn bool Window.is_key_released(&self, Key) @cname("RGFW_window_isKeyReleased");
+extern fn bool Window.is_mouse_pressed(&self, MouseButton) @cname("RGFW_window_isMousePressed");
+extern fn bool Window.is_mouse_down(&self, MouseButton) @cname("RGFW_window_isMouseDown");
+extern fn bool Window.is_mouse_released(&self, MouseButton) @cname("RGFW_window_isMouseReleased");
+extern fn bool Window.did_mouse_leave(&self) @cname("RGFW_window_didMouseLeave");
+extern fn bool Window.did_mouse_enter(&self) @cname("RGFW_window_didMouseEnter");
+extern fn bool Window.is_mouse_inside(&self) @cname("RGFW_window_isMouseInside");
+extern fn bool Window.is_data_dragging(&self) @cname("RGFW_window_isDataDragging");
+extern fn bool Window.get_data_drag(&self, int*, int*) @cname("RGFW_window_getDataDrag");
+extern fn bool Window.did_data_drop(&self) @cname("RGFW_window_didDataDrop");
+extern fn DataDropNode* Window.get_data_drop(&self) @cname("RGFW_window_getDataDrop");
+extern fn void Window.close(&self) @cname("RGFW_window_close");
+extern fn void Window.close_ptr(&self) @cname("RGFW_window_closePtr");
+extern fn bool Window.fetch_size(&self, int*, int*) @cname("RGFW_window_fetchSize");
+extern fn void Window.move(&self, int, int) @cname("RGFW_window_move");
+extern fn void Window.move_to_monitor(&self, Monitor*) @cname("RGFW_window_moveToMonitor");
+extern fn void Window.resize(&self, int, int) @cname("RGFW_window_resize");
+extern fn void Window.set_aspect_ratio(&self, int, int) @cname("RGFW_window_setAspectRatio");
+extern fn void Window.set_min_size(&self, int, int) @cname("RGFW_window_setMinSize");
+extern fn void Window.set_max_size(&self, int, int) @cname("RGFW_window_setMaxSize");
+extern fn void Window.focus(&self) @cname("RGFW_window_focus");
+extern fn bool Window.is_in_focus(&self) @cname("RGFW_window_isInFocus");
+extern fn void Window.raise(&self) @cname("RGFW_window_raise");
+extern fn void Window.maximize(&self) @cname("RGFW_window_maximize");
+extern fn void Window.set_fullscreen(&self, bool) @cname("RGFW_window_setFullscreen");
+extern fn void Window.center(&self) @cname("RGFW_window_center");
+extern fn void Window.minimize(&self) @cname("RGFW_window_minimize");
+extern fn void Window.restore(&self) @cname("RGFW_window_restore");
+extern fn void Window.set_floating(&self, bool) @cname("RGFW_window_setFloating");
+extern fn void Window.set_opacity(&self, char) @cname("RGFW_window_setOpacity");
+extern fn void Window.set_border(&self, bool) @cname("RGFW_window_setBorder");
+extern fn bool Window.borderless(&self) @cname("RGFW_window_borderless");
+extern fn void Window.set_DND(&self, bool) @cname("RGFW_window_setDND");
+extern fn bool Window.allows_DND(&self) @cname("RGFW_window_allowsDND");
+extern fn void Window.set_mouse_passthrough(&self, bool) @cname("RGFW_window_setMousePassthrough");
+extern fn void Window.set_name(&self, ZString) @cname("RGFW_window_setName");
+extern fn bool Window.set_icon(&self, char*, int, int, Format) @cname("RGFW_window_seticon");
+extern fn bool Window.set_icon_ex(&self, char*, int, int, Format, Icon) @cname("RGFW_window_setIconEx");
+extern fn bool Window.set_mouse(&self, Mouse*) @cname("RGFW_window_setMouse");
+extern fn bool Window.set_mouse_standard(&self, MouseIcon) @cname("RGFW_window_setMouseStandard");
+extern fn bool Window.set_mouse_default(&self) @cname("RGFW_window_setMouseDefault");
+extern fn void Window.set_raw_mouse_mode(&self, bool) @cname("RGFW_window_setRawMouseMode");
+extern fn void Window.capture_mouse(&self, bool) @cname("RGFW_window_captureMouse");
+extern fn void Window.capture_raw_mouse_mode(&self, bool) @cname("RGFW_window_captureRawMouse");
+extern fn bool Window.is_raw_mouse_mode(&self) @cname("RGFW_window_isRawMouseMode");
+extern fn bool Window.is_captured(&self) @cname("RGFW_window_isCaptured");
+extern fn void Window.hide(&self) @cname("RGFW_window_hide");
+extern fn void Window.show(&self) @cname("RGFW_window_show");
+extern fn void Window.flash(&self, FlashRequest) @cname("RGFW_window_flash");
+extern fn void Window.set_should_close(&self, bool) @cname("RGFW_window_setShouldClose");
+extern fn bool get_global_mouse(int*, int*) @cname("RGFW_getGlobalMouse");
+extern fn bool Window.get_mouse(&self, int*, int*) @cname("RGFW_window_getMouse");
+extern fn void Window.show_mouse(&self, bool) @cname("RGFW_window_showMouse");
+extern fn bool Window.is_mouse_hidden(&self) @cname("RGFW_window_isMouseHidden");
+extern fn void Window.move_mouse(&self, int, int) @cname("RGFW_window_moveMouse");
+extern fn bool Window.should_close(&self) @cname("RGFW_window_shouldClose");
+extern fn bool Window.is_fullscreen(&self) @cname("RGFW_window_isFullscreen");
+extern fn bool Window.is_fullscreen_exclusive(&self) @cname("RGFW_window_isFullscreenExclusive");
+extern fn bool Window.is_fullscreen_borderless(&self) @cname("RGFW_window_isFullscreenBorderless");
+extern fn bool Window.is_hidden(&self) @cname("RGFW_window_isHidden");
+extern fn bool Window.is_minimized(&self) @cname("RGFW_window_isMinimized");
+extern fn bool Window.is_maximized(&self) @cname("RGFW_window_isMaximized");
+extern fn bool Window.is_floating(&self) @cname("RGFW_window_isFloating");
+extern fn void Window.scale_to_monitor(&self) @cname("RGFW_window_scaleToMonitor");
+extern fn Monitor* Window.get_monitor(&self) @cname("RGFW_window_getMonitor");
+extern fn DataTransfer* read_clipboard(DataTransferType) @cname("RGFW_readClipboard");
+extern fn bool read_clipboard_ptr(DataTransferType, char*, usz, DataTransfer*) @cname("RGFW_readClipboardPtr");
+// TODO tell upstream the following function's docs are wrong
+extern fn DataTransfer* read_clipboard_string() @cname("RGFW_readClipboardString");
+extern fn bool read_clipboard_string_ptr(char*, usz, DataTransfer*) @cname("RGFW_readClipboardStringPtr");
+extern fn bool write_clipboard(DataTransfer*) @cname("RGFW_writeClipboard");
+extern fn DebugFunc set_debug_callback(DebugFunc) @cname("RGFW_setDebugCallback");
+extern fn void debug_callback(DebugType, ErrorCode, ZString) @cname("RGFW_debugCallback");
+extern fn void Window.set_root(&self) @cname("RGFW_setRootWindow");
+extern fn Window* get_root_window() @cname("RGFW_getRootWindow");
+extern fn void event_queue_push(Event*) @cname("RGFW_eventQueuePush");
+extern fn void event_queue_push_and_call(Event*) @cname("RGFW_eventQueuePushAndCall");
+extern fn void event_queue_flush() @cname("RGFW_eventQueueFlush");
+extern fn Event* event_queue_pop() @cname("RGFW_eventQueuePop");
+extern fn Event* Window.event_queue_pop(&self) @cname("RGFW_window_eventQueuePop");
+extern fn Key api_key_to_rgfw(uint) @cname("RGFW_apiKeyToRGFW");
+extern fn uint rgfw_to_api_key(Key) @cname("RGFW_rgfwToApiKey");
+extern fn Key physical_to_mapped_key(Key) @cname("RGFW_physicalToMappedKey");
+
+module rgfw::opengl @feat(OPENGL | EGL);
+extern fn void set_global_hints(GlHints*) @cname("RGFW_setGlobalHints_OpenGL");
+extern fn void reset_global_hints() @cname("RGFW_resetGlobalHints_OpenGL");
+extern fn GlHints* get_global_hints() @cname("RGFW_getGlobalHints_OpenGL");
+
+module rgfw::opengl @feat(OPENGL);
+extern fn GlContext* create_context(GlHints*) @cname("RGFW_createContext_OpenGL");
+extern fn bool create_context_ptr(GlContext*, GlHints*) @cname("RGFW_createContextPtr_OpenGL");
+extern fn void delete_context(GlContext*) @cname("RGFW_deleteContext_OpenGL");
+extern fn void delete_context_ptr(GlContext*) @cname("RGFW_deleteContextPtr_OpenGL");
+extern fn GlContext* copy_context(GlContext*) @cname("RGFW_copyContext_OpenGL");
+extern fn bool copy_context_ptr(GlContext*, GlContext*) @cname("RGFW_copyContextPtr_OpenGL");
+extern fn void* GlContext.get_source_context(&self) @cname("RGFW_glContext_getSourceContext");
+extern fn void* get_current_context() @cname("RGFW_getCurrentContext_OpenGL");
+extern fn void* get_current_surface() @cname("RGFW_getCurrentSurface_OpenGL");
+extern fn Window* get_current_window() @cname("RGFW_getCurrentWindow_OpenGL");
+extern fn Proc get_proc_address(ZString) @cname("RGFW_getProcAddress_OpenGL");
+extern fn bool extension_supported(ZString, usz) @cname("RGFW_extensionSupported_OpenGL");
+extern fn bool extension_supported_platform(ZString, usz) @cname("RGFW_extensionSupportedPlatform_OpenGL");
+
+// if EGL is defined, prefer those methods as they (should) fall back
+module rgfw::opengl @feat(OPENGL & !EGL);
+extern fn bool Window.set_context(&self, GlContext*) @cname("RGFW_window_setContext_OpenGL");
+extern fn GlContext* Window.get_context(&self) @cname("RGFW_window_getContext_OpenGL");
+extern fn void Window.make_current_window(&self) @cname("RGFW_window_makeCurrentWindow_OpenGL");
+extern fn void Window.make_current_context(&self) @cname("RGFW_window_makeCurrentContext_OpenGL");
+extern fn void Window.swap_buffers(&self) @cname("RGFW_window_swapBuffers_OpenGL");
+extern fn void Window.swap_interval(&self, int) @cname("RGFW_window_swapInterval_OpenGL");
+
+module rgfw::egl @feat(EGL);
+extern fn EglContext* create_context(GlHints*) @cname("RGFW_window_createContext_EGL");
+extern fn bool create_context_ptr(EglContext*, GlHints*) @cname("RGFW_window_createContextPtr_EGL");
+extern fn void delete_context(EglContext*) @cname("RGFW_window_deleteContext_EGL");
+extern fn void delete_context_ptr(EglContext*) @cname("RGFW_window_deleteContextPtr_EGL");
+extern fn EglContext* copy_context(EglContext*) @cname("RGFW_copyContext_EGL");
+extern fn bool copy_context_ptr(EglContext*, EglContext*) @cname("RGFW_copyContextPtr_EGL");
+extern fn bool Window.set_context(&self, EglContext*) @cname("RGFW_window_setContext_EGL");
+extern fn EglContext* Window.get_context(&self) @cname("RGFW_window_getContext_EGL");
+extern fn void* get_display() @cname("RGFW_getDisplay_EGL");
+extern fn void* EglContext.get_source_context(&self) @cname("RGFW_eglContext_getSourceContext");
+extern fn void* EglContext.get_surface(&self) @cname("RGFW_eglContext_getSurface");
+extern fn void* EglContext.wl_egl_window(&self) @cname("RGFW_eglContext_wlEGLWindow");
+extern fn void Window.swap_buffers(&self) @cname("RGFW_window_swapBuffers_EGL");
+extern fn void Window.make_current_window(&self) @cname("RGFW_window_makeCurrentWindow_EGL");
+extern fn void Window.make_current_context(&self) @cname("RGFW_window_makeCurrentContext_EGL");
+extern fn void* get_current_context() @cname("RGFW_getCurrentContext_EGL");
+extern fn void* get_current_surface() @cname("RGFW_getCurrentSurface_EGL");
+extern fn Window* get_current_window() @cname("RGFW_getCurrentWindow_EGL");
+extern fn void Window.swap_interval(&self, int) @cname("RGFW_window_swapInterval_EGL");
+extern fn Proc get_proc_address(ZString) @cname("RGFW_getProcAddress_EGL");
+extern fn bool extension_supported(ZString, usz) @cname("RGFW_extensionSupported_EGL");
+extern fn bool extension_supported_platform(ZString, usz) @cname("RGFW_extensionSupportedPlatform_EGL");
-module rgfw::opengl @if($feature(OPENGL));
-extern fn void setGlobalHints(GlHints*) @cname("RGFW_setGlobalHints_OpenGL");
-extern fn void resetGlobalHints() @cname("RGFW_resetGlobalHints_OpenGL");
-extern fn GlHints* getGlobalHints() @cname("RGFW_getGlobalHints_OpenGL");
-extern fn GlContext* window_createContext(Window*, GlHints*) @cname("RGFW_window_createContext_OpenGL");
-extern fn bool window_createContextPtr(Window*, GlContext*, GlHints*) @cname("RGFW_window_createContextPtr_OpenGL");
-extern fn GlContext* window_getContext(Window*) @cname("RGFW_window_getContext_OpenGL");
-extern fn void window_deleteContext(Window*, GlContext*) @cname("RGFW_window_deleteContext_OpenGL");
-extern fn void window_deleteContextPtr(Window*, GlContext*) @cname("RGFW_window_deleteContextPtr_OpenGL");
-extern fn void* glContext_getSourceContext(GlContext*) @cname("RGFW_glContext_getSourceContext");
-extern fn void window_makeCurrentWindow(Window*) @cname("RGFW_window_makeCurrentWindow_OpenGL");
-extern fn void window_makeCurrentContext(Window*) @cname("RGFW_window_makeCurrentContext_OpenGL");
-extern fn void window_swapBuffers(Window*) @cname("RGFW_window_swapBuffers_OpenGL");
-extern fn void* getCurrentContext() @cname("RGFW_getCurrentContext_OpenGL");
-extern fn Window* getCurrentWindow() @cname("RGFW_getCurrentWindow_OpenGL");
-extern fn void window_swapInterval(Window*, int) @cname("RGFW_window_swapInterval_OpenGL");
-extern fn Proc getProcAddress(ZString) @cname("RGFW_getProcAddress_OpenGL");
-extern fn bool extensionSupported(ZString, usz) @cname("RGFW_extensionSupported_OpenGL");
-extern fn bool extensionSupportedPlatform(ZString, usz) @cname("RGFW_extensionSupportedPlatform_OpenGL");
+module rgfw::vulkan @feat(VULKAN);
+alias VkResult = int;
+alias VkInstance = void*;
+alias VkSurfaceKHR = ulong;
+alias VkPhysicalDevice = void*;
+extern fn Proc VkInstance.get_proc_address(self, ZString) @cname("RGFW_getInstanceProcAddress_Vulkan");
+extern fn ZString[] get_required_instance_extensions(usz*) @cname("RGFW_getRequiredInstanceExtensions_Vulkan");
+extern fn VkResult create_surface(Window*, VkInstance, VkSurfaceKHR*) @cname("RGFW_window_createSurface_Vulkan");
+extern fn bool VkInstance.get_physical_device_presentation_support(
+ self,
+ VkPhysicalDevice,
+ uint
+) @cname("RGFW_getPhysicalDevicePresentationSupport_Vulkan");
-// RGFW_EGL
-module rgfw::egl @if($feature(EGL));
-extern fn EglContext* window_createContext(Window*, GlHints*) @cname("RGFW_window_createContext_EGL");
-extern fn bool window_createContextPtr(Window*, EglContext*, GlHints*) @cname("RGFW_window_createContextPtr_EGL");
-extern fn void window_deleteContext(Window*, EglContext*) @cname("RGFW_window_deleteContext_EGL");
-extern fn void window_deleteContextPtr(Window*, EglContext*) @cname("RGFW_window_deleteContextPtr_EGL");
-extern fn EglContext* window_getContext(Window*) @cname("RGFW_window_getContext_EGL");
-extern fn void* getDisplay() @cname("RGFW_getDisplay_EGL");
-extern fn void* eglContext_getSourceContext(EglContext*) @cname("RGFW_eglContext_getSourceContext");
-extern fn void* eglContext_getSurface(EglContext*) @cname("RGFW_eglContext_getSurface");
-extern fn void* eglContext_wlEglWindow(EglContext*) @cname("RGFW_eglContext_wlEGLWindow");
-extern fn void window_swapBuffers(Window*) @cname("RGFW_window_swapBuffers_EGL");
-extern fn void window_makeCurrentWindow(Window*) @cname("RGFW_window_makeCurrentWindow_EGL");
-extern fn void window_makeCurrentContext(Window*) @cname("RGFW_window_makeCurrentContext_EGL");
-extern fn void* getCurrentContext() @cname("RGFW_getCurrentContext_EGL");
-extern fn Window* getCurrentWindow() @cname("RGFW_getCurrentWindow_EGL");
-extern fn void window_swapInterval(Window*, int) @cname("RGFW_window_swapInterval_EGL");
-extern fn Proc* getProcAddress(ZString) @cname("RGFW_getProcAddress_EGL");
-extern fn bool extensionSupported(ZString, usz) @cname("RGFW_extensionSupported_EGL");
-extern fn bool extensionSupportedPlatform(ZString, usz) @cname("RGFW_extensionSupportedPlatform_EGL");
+module rgfw::directx @feat(DIRECTX);
+alias IDXGIFactory = void;
+alias IUnknown = void;
+alias UDXGISwapChain = void;
+extern fn int create_swap_chain(Window*, IDXGIFactory*, IUnknown*, UDXGISwapChain**) @cname("RGFW_window_createSwapChain_DirectX");
-// RGFW_VULKAN 2599..2626
-// RGFW_DIRECTX 2630..2649
-// RGFW_WEBGPU 2652..2661
+module rgfw::wgpu @feat(WGPU);
+alias WGPUSurface = void*;
+alias WGPUInstance = void*;
+extern fn WGPUSurface create_surface(Window*, WGPUInstance) @cname("RGFW_window_createSurface_WebGPU");